]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix mouse spinning bug in wgl client when the game window is moved left or above...
[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"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
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"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
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_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
129 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
130 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
131 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."};
132 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
133 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
134 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
135 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."};
136 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
137 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
138 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
139 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."};
140 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
141 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"};
142 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"};
143 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
144 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
145 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
146 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
147 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
148 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"};
149 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
150 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
151 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
152 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
153 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
154
155 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
156 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
157 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
158 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
159 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
160 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
161 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
162 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
163
164 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)"};
165 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"};
166
167 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
168 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
169 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
170
171 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"};
172 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"};
173 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"};
174 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
175 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
176 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"};
177 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)"};
178 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)"};
179 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
180
181 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
182 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)"};
183 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
184 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)"};
185 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
186 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)"};
187 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)"};
188 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
189 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"};
190 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."};
191 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199 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)"};
200
201 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)"};
202 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)"};
203 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
204 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"};
205 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
206 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
207 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
208 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"};
209 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"};
210 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)"};
211
212 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
213 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
214 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
215 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
216
217 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
218 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
219
220 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
221 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
222 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
223 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
224 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
225 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
226
227 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
228 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
229 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
230 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
231 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
232 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
233 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
234 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
235 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
236 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
237
238 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"};
239
240 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"};
241
242 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
243
244 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
245
246 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)"};
247 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)"};
248 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
249 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
250
251 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
252 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"};
253
254 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."};
255
256 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)"};
257 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
258 {
259         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
260         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
261         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
262         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
263 };
264
265 extern cvar_t v_glslgamma;
266 extern cvar_t v_glslgamma_2d;
267
268 extern qboolean v_flipped_state;
269
270 r_framebufferstate_t r_fb;
271
272 /// shadow volume bsp struct with automatically growing nodes buffer
273 svbsp_t r_svbsp;
274
275 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
276
277 rtexture_t *r_texture_blanknormalmap;
278 rtexture_t *r_texture_white;
279 rtexture_t *r_texture_grey128;
280 rtexture_t *r_texture_black;
281 rtexture_t *r_texture_notexture;
282 rtexture_t *r_texture_whitecube;
283 rtexture_t *r_texture_normalizationcube;
284 rtexture_t *r_texture_fogattenuation;
285 rtexture_t *r_texture_fogheighttexture;
286 rtexture_t *r_texture_gammaramps;
287 unsigned int r_texture_gammaramps_serial;
288 //rtexture_t *r_texture_fogintensity;
289 rtexture_t *r_texture_reflectcube;
290
291 // TODO: hash lookups?
292 typedef struct cubemapinfo_s
293 {
294         char basename[64];
295         rtexture_t *texture;
296 }
297 cubemapinfo_t;
298
299 int r_texture_numcubemaps;
300 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
301
302 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
303 unsigned int r_numqueries;
304 unsigned int r_maxqueries;
305
306 typedef struct r_qwskincache_s
307 {
308         char name[MAX_QPATH];
309         skinframe_t *skinframe;
310 }
311 r_qwskincache_t;
312
313 static r_qwskincache_t *r_qwskincache;
314 static int r_qwskincache_size;
315
316 /// vertex coordinates for a quad that covers the screen exactly
317 extern const float r_screenvertex3f[12];
318 extern const float r_d3dscreenvertex3f[12];
319 const float r_screenvertex3f[12] =
320 {
321         0, 0, 0,
322         1, 0, 0,
323         1, 1, 0,
324         0, 1, 0
325 };
326 const float r_d3dscreenvertex3f[12] =
327 {
328         0, 1, 0,
329         1, 1, 0,
330         1, 0, 0,
331         0, 0, 0
332 };
333
334 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = in[0] * r;
340                 out[1] = in[1] * g;
341                 out[2] = in[2] * b;
342                 out[3] = in[3];
343                 in += 4;
344                 out += 4;
345         }
346 }
347
348 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
349 {
350         int i;
351         for (i = 0;i < verts;i++)
352         {
353                 out[0] = r;
354                 out[1] = g;
355                 out[2] = b;
356                 out[3] = a;
357                 out += 4;
358         }
359 }
360
361 // FIXME: move this to client?
362 void FOG_clear(void)
363 {
364         if (gamemode == GAME_NEHAHRA)
365         {
366                 Cvar_Set("gl_fogenable", "0");
367                 Cvar_Set("gl_fogdensity", "0.2");
368                 Cvar_Set("gl_fogred", "0.3");
369                 Cvar_Set("gl_foggreen", "0.3");
370                 Cvar_Set("gl_fogblue", "0.3");
371         }
372         r_refdef.fog_density = 0;
373         r_refdef.fog_red = 0;
374         r_refdef.fog_green = 0;
375         r_refdef.fog_blue = 0;
376         r_refdef.fog_alpha = 1;
377         r_refdef.fog_start = 0;
378         r_refdef.fog_end = 16384;
379         r_refdef.fog_height = 1<<30;
380         r_refdef.fog_fadedepth = 128;
381         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
382 }
383
384 static void R_BuildBlankTextures(void)
385 {
386         unsigned char data[4];
387         data[2] = 128; // normal X
388         data[1] = 128; // normal Y
389         data[0] = 255; // normal Z
390         data[3] = 255; // height
391         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392         data[0] = 255;
393         data[1] = 255;
394         data[2] = 255;
395         data[3] = 255;
396         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 128;
398         data[1] = 128;
399         data[2] = 128;
400         data[3] = 255;
401         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 0;
403         data[1] = 0;
404         data[2] = 0;
405         data[3] = 255;
406         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNoTexture(void)
410 {
411         int x, y;
412         unsigned char pix[16][16][4];
413         // this makes a light grey/dark grey checkerboard texture
414         for (y = 0;y < 16;y++)
415         {
416                 for (x = 0;x < 16;x++)
417                 {
418                         if ((y < 8) ^ (x < 8))
419                         {
420                                 pix[y][x][0] = 128;
421                                 pix[y][x][1] = 128;
422                                 pix[y][x][2] = 128;
423                                 pix[y][x][3] = 255;
424                         }
425                         else
426                         {
427                                 pix[y][x][0] = 64;
428                                 pix[y][x][1] = 64;
429                                 pix[y][x][2] = 64;
430                                 pix[y][x][3] = 255;
431                         }
432                 }
433         }
434         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
435 }
436
437 static void R_BuildWhiteCube(void)
438 {
439         unsigned char data[6*1*1*4];
440         memset(data, 255, sizeof(data));
441         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
442 }
443
444 static void R_BuildNormalizationCube(void)
445 {
446         int x, y, side;
447         vec3_t v;
448         vec_t s, t, intensity;
449 #define NORMSIZE 64
450         unsigned char *data;
451         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
452         for (side = 0;side < 6;side++)
453         {
454                 for (y = 0;y < NORMSIZE;y++)
455                 {
456                         for (x = 0;x < NORMSIZE;x++)
457                         {
458                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
460                                 switch(side)
461                                 {
462                                 default:
463                                 case 0:
464                                         v[0] = 1;
465                                         v[1] = -t;
466                                         v[2] = -s;
467                                         break;
468                                 case 1:
469                                         v[0] = -1;
470                                         v[1] = -t;
471                                         v[2] = s;
472                                         break;
473                                 case 2:
474                                         v[0] = s;
475                                         v[1] = 1;
476                                         v[2] = t;
477                                         break;
478                                 case 3:
479                                         v[0] = s;
480                                         v[1] = -1;
481                                         v[2] = -t;
482                                         break;
483                                 case 4:
484                                         v[0] = s;
485                                         v[1] = -t;
486                                         v[2] = 1;
487                                         break;
488                                 case 5:
489                                         v[0] = -s;
490                                         v[1] = -t;
491                                         v[2] = -1;
492                                         break;
493                                 }
494                                 intensity = 127.0f / sqrt(DotProduct(v, v));
495                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
496                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
497                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
498                                 data[((side*64+y)*64+x)*4+3] = 255;
499                         }
500                 }
501         }
502         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
503         Mem_Free(data);
504 }
505
506 static void R_BuildFogTexture(void)
507 {
508         int x, b;
509 #define FOGWIDTH 256
510         unsigned char data1[FOGWIDTH][4];
511         //unsigned char data2[FOGWIDTH][4];
512         double d, r, alpha;
513
514         r_refdef.fogmasktable_start = r_refdef.fog_start;
515         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
516         r_refdef.fogmasktable_range = r_refdef.fogrange;
517         r_refdef.fogmasktable_density = r_refdef.fog_density;
518
519         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
520         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
521         {
522                 d = (x * r - r_refdef.fogmasktable_start);
523                 if(developer_extra.integer)
524                         Con_DPrintf("%f ", d);
525                 d = max(0, d);
526                 if (r_fog_exp2.integer)
527                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
528                 else
529                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
530                 if(developer_extra.integer)
531                         Con_DPrintf(" : %f ", alpha);
532                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
533                 if(developer_extra.integer)
534                         Con_DPrintf(" = %f\n", alpha);
535                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
536         }
537
538         for (x = 0;x < FOGWIDTH;x++)
539         {
540                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541                 data1[x][0] = b;
542                 data1[x][1] = b;
543                 data1[x][2] = b;
544                 data1[x][3] = 255;
545                 //data2[x][0] = 255 - b;
546                 //data2[x][1] = 255 - b;
547                 //data2[x][2] = 255 - b;
548                 //data2[x][3] = 255;
549         }
550         if (r_texture_fogattenuation)
551         {
552                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
554         }
555         else
556         {
557                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
558                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
559         }
560 }
561
562 static void R_BuildFogHeightTexture(void)
563 {
564         unsigned char *inpixels;
565         int size;
566         int x;
567         int y;
568         int j;
569         float c[4];
570         float f;
571         inpixels = NULL;
572         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
573         if (r_refdef.fogheighttexturename[0])
574                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
575         if (!inpixels)
576         {
577                 r_refdef.fog_height_tablesize = 0;
578                 if (r_texture_fogheighttexture)
579                         R_FreeTexture(r_texture_fogheighttexture);
580                 r_texture_fogheighttexture = NULL;
581                 if (r_refdef.fog_height_table2d)
582                         Mem_Free(r_refdef.fog_height_table2d);
583                 r_refdef.fog_height_table2d = NULL;
584                 if (r_refdef.fog_height_table1d)
585                         Mem_Free(r_refdef.fog_height_table1d);
586                 r_refdef.fog_height_table1d = NULL;
587                 return;
588         }
589         size = image_width;
590         r_refdef.fog_height_tablesize = size;
591         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
592         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
593         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
594         Mem_Free(inpixels);
595         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
596         // average fog color table accounting for every fog layer between a point
597         // and the camera.  (Note: attenuation is handled separately!)
598         for (y = 0;y < size;y++)
599         {
600                 for (x = 0;x < size;x++)
601                 {
602                         Vector4Clear(c);
603                         f = 0;
604                         if (x < y)
605                         {
606                                 for (j = x;j <= y;j++)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         else
613                         {
614                                 for (j = x;j >= y;j--)
615                                 {
616                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617                                         f++;
618                                 }
619                         }
620                         f = 1.0f / f;
621                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
622                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
623                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
624                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
625                 }
626         }
627         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
628 }
629
630 //=======================================================================================================================================================
631
632 static const char *builtinshaderstrings[] =
633 {
634 #include "shader_glsl.h"
635 0
636 };
637
638 const char *builtinhlslshaderstrings[] =
639 {
640 #include "shader_hlsl.h"
641 0
642 };
643
644 //=======================================================================================================================================================
645
646 typedef struct shaderpermutationinfo_s
647 {
648         const char *pretext;
649         const char *name;
650 }
651 shaderpermutationinfo_t;
652
653 typedef struct shadermodeinfo_s
654 {
655         const char *sourcebasename;
656         const char *extension;
657         const char **builtinshaderstrings;
658         const char *pretext;
659         const char *name;
660         char *filename;
661         char *builtinstring;
662         int builtincrc;
663 }
664 shadermodeinfo_t;
665
666 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
667 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
668 {
669         {"#define USEDIFFUSE\n", " diffuse"},
670         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
671         {"#define USEVIEWTINT\n", " viewtint"},
672         {"#define USECOLORMAPPING\n", " colormapping"},
673         {"#define USESATURATION\n", " saturation"},
674         {"#define USEFOGINSIDE\n", " foginside"},
675         {"#define USEFOGOUTSIDE\n", " fogoutside"},
676         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
677         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
678         {"#define USEGAMMARAMPS\n", " gammaramps"},
679         {"#define USECUBEFILTER\n", " cubefilter"},
680         {"#define USEGLOW\n", " glow"},
681         {"#define USEBLOOM\n", " bloom"},
682         {"#define USESPECULAR\n", " specular"},
683         {"#define USEPOSTPROCESSING\n", " postprocessing"},
684         {"#define USEREFLECTION\n", " reflection"},
685         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
686         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
687         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
688         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
689         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
690         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
691         {"#define USEALPHAKILL\n", " alphakill"},
692         {"#define USEREFLECTCUBE\n", " reflectcube"},
693         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
694         {"#define USEBOUNCEGRID\n", " bouncegrid"},
695         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
696         {"#define USETRIPPY\n", " trippy"},
697         {"#define USEDEPTHRGB\n", " depthrgb"},
698         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
699         {"#define USESKELETAL\n", " skeletal"},
700         {"#define USEOCCLUDE\n", " occlude"}
701 };
702
703 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
704 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
705 {
706         // SHADERLANGUAGE_GLSL
707         {
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725         },
726         // SHADERLANGUAGE_HLSL
727         {
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
745         },
746 };
747
748 struct r_glsl_permutation_s;
749 typedef struct r_glsl_permutation_s
750 {
751         /// hash lookup data
752         struct r_glsl_permutation_s *hashnext;
753         unsigned int mode;
754         dpuint64 permutation;
755
756         /// indicates if we have tried compiling this permutation already
757         qboolean compiled;
758         /// 0 if compilation failed
759         int program;
760         // texture units assigned to each detected uniform
761         int tex_Texture_First;
762         int tex_Texture_Second;
763         int tex_Texture_GammaRamps;
764         int tex_Texture_Normal;
765         int tex_Texture_Color;
766         int tex_Texture_Gloss;
767         int tex_Texture_Glow;
768         int tex_Texture_SecondaryNormal;
769         int tex_Texture_SecondaryColor;
770         int tex_Texture_SecondaryGloss;
771         int tex_Texture_SecondaryGlow;
772         int tex_Texture_Pants;
773         int tex_Texture_Shirt;
774         int tex_Texture_FogHeightTexture;
775         int tex_Texture_FogMask;
776         int tex_Texture_Lightmap;
777         int tex_Texture_Deluxemap;
778         int tex_Texture_Attenuation;
779         int tex_Texture_Cube;
780         int tex_Texture_Refraction;
781         int tex_Texture_Reflection;
782         int tex_Texture_ShadowMap2D;
783         int tex_Texture_CubeProjection;
784         int tex_Texture_ScreenNormalMap;
785         int tex_Texture_ScreenDiffuse;
786         int tex_Texture_ScreenSpecular;
787         int tex_Texture_ReflectMask;
788         int tex_Texture_ReflectCube;
789         int tex_Texture_BounceGrid;
790         /// locations of detected uniforms in program object, or -1 if not found
791         int loc_Texture_First;
792         int loc_Texture_Second;
793         int loc_Texture_GammaRamps;
794         int loc_Texture_Normal;
795         int loc_Texture_Color;
796         int loc_Texture_Gloss;
797         int loc_Texture_Glow;
798         int loc_Texture_SecondaryNormal;
799         int loc_Texture_SecondaryColor;
800         int loc_Texture_SecondaryGloss;
801         int loc_Texture_SecondaryGlow;
802         int loc_Texture_Pants;
803         int loc_Texture_Shirt;
804         int loc_Texture_FogHeightTexture;
805         int loc_Texture_FogMask;
806         int loc_Texture_Lightmap;
807         int loc_Texture_Deluxemap;
808         int loc_Texture_Attenuation;
809         int loc_Texture_Cube;
810         int loc_Texture_Refraction;
811         int loc_Texture_Reflection;
812         int loc_Texture_ShadowMap2D;
813         int loc_Texture_CubeProjection;
814         int loc_Texture_ScreenNormalMap;
815         int loc_Texture_ScreenDiffuse;
816         int loc_Texture_ScreenSpecular;
817         int loc_Texture_ReflectMask;
818         int loc_Texture_ReflectCube;
819         int loc_Texture_BounceGrid;
820         int loc_Alpha;
821         int loc_BloomBlur_Parameters;
822         int loc_ClientTime;
823         int loc_Color_Ambient;
824         int loc_Color_Diffuse;
825         int loc_Color_Specular;
826         int loc_Color_Glow;
827         int loc_Color_Pants;
828         int loc_Color_Shirt;
829         int loc_DeferredColor_Ambient;
830         int loc_DeferredColor_Diffuse;
831         int loc_DeferredColor_Specular;
832         int loc_DeferredMod_Diffuse;
833         int loc_DeferredMod_Specular;
834         int loc_DistortScaleRefractReflect;
835         int loc_EyePosition;
836         int loc_FogColor;
837         int loc_FogHeightFade;
838         int loc_FogPlane;
839         int loc_FogPlaneViewDist;
840         int loc_FogRangeRecip;
841         int loc_LightColor;
842         int loc_LightDir;
843         int loc_LightPosition;
844         int loc_OffsetMapping_ScaleSteps;
845         int loc_OffsetMapping_LodDistance;
846         int loc_OffsetMapping_Bias;
847         int loc_PixelSize;
848         int loc_ReflectColor;
849         int loc_ReflectFactor;
850         int loc_ReflectOffset;
851         int loc_RefractColor;
852         int loc_Saturation;
853         int loc_ScreenCenterRefractReflect;
854         int loc_ScreenScaleRefractReflect;
855         int loc_ScreenToDepth;
856         int loc_ShadowMap_Parameters;
857         int loc_ShadowMap_TextureScale;
858         int loc_SpecularPower;
859         int loc_Skeletal_Transform12;
860         int loc_UserVec1;
861         int loc_UserVec2;
862         int loc_UserVec3;
863         int loc_UserVec4;
864         int loc_ViewTintColor;
865         int loc_ViewToLight;
866         int loc_ModelToLight;
867         int loc_TexMatrix;
868         int loc_BackgroundTexMatrix;
869         int loc_ModelViewProjectionMatrix;
870         int loc_ModelViewMatrix;
871         int loc_PixelToScreenTexCoord;
872         int loc_ModelToReflectCube;
873         int loc_ShadowMapMatrix;
874         int loc_BloomColorSubtract;
875         int loc_NormalmapScrollBlend;
876         int loc_BounceGridMatrix;
877         int loc_BounceGridIntensity;
878         /// uniform block bindings
879         int ubibind_Skeletal_Transform12_UniformBlock;
880         /// uniform block indices
881         int ubiloc_Skeletal_Transform12_UniformBlock;
882 }
883 r_glsl_permutation_t;
884
885 #define SHADERPERMUTATION_HASHSIZE 256
886
887
888 // non-degradable "lightweight" shader parameters to keep the permutations simpler
889 // these can NOT degrade! only use for simple stuff
890 enum
891 {
892         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
893         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
894         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
895         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
896         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
897         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
898         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
899         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
900         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
901         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
902         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
903         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
904         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
905         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
906 };
907 #define SHADERSTATICPARMS_COUNT 14
908
909 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
910 static int shaderstaticparms_count = 0;
911
912 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
913 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
914
915 extern qboolean r_shadow_shadowmapsampler;
916 extern int r_shadow_shadowmappcf;
917 qboolean R_CompileShader_CheckStaticParms(void)
918 {
919         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
920         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
921         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
922
923         // detect all
924         if (r_glsl_saturation_redcompensate.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
926         if (r_glsl_vertextextureblend_usebothalphas.integer)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
928         if (r_shadow_glossexact.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
930         if (r_glsl_postprocess.integer)
931         {
932                 if (r_glsl_postprocess_uservec1_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
934                 if (r_glsl_postprocess_uservec2_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
936                 if (r_glsl_postprocess_uservec3_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
938                 if (r_glsl_postprocess_uservec4_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
940         }
941         if (r_fxaa.integer)
942                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
943         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
944                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
945
946         if (r_shadow_shadowmapsampler)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
948         if (r_shadow_shadowmappcf > 1)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
950         else if (r_shadow_shadowmappcf)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
952         if (r_celshading.integer)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
954         if (r_celoutlines.integer)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
956
957         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
958 }
959
960 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
961         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
962                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
963         else \
964                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
965 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
966 {
967         shaderstaticparms_count = 0;
968
969         // emit all
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
984 }
985
986 /// information about each possible shader permutation
987 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
988 /// currently selected permutation
989 r_glsl_permutation_t *r_glsl_permutation;
990 /// storage for permutations linked in the hash table
991 memexpandablearray_t r_glsl_permutationarray;
992
993 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
994 {
995         //unsigned int hashdepth = 0;
996         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
997         r_glsl_permutation_t *p;
998         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
999         {
1000                 if (p->mode == mode && p->permutation == permutation)
1001                 {
1002                         //if (hashdepth > 10)
1003                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1004                         return p;
1005                 }
1006                 //hashdepth++;
1007         }
1008         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1009         p->mode = mode;
1010         p->permutation = permutation;
1011         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1012         r_glsl_permutationhash[mode][hashindex] = p;
1013         //if (hashdepth > 10)
1014         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1015         return p;
1016 }
1017
1018 static char *R_ShaderStrCat(const char **strings)
1019 {
1020         char *string, *s;
1021         const char **p = strings;
1022         const char *t;
1023         size_t len = 0;
1024         for (p = strings;(t = *p);p++)
1025                 len += strlen(t);
1026         len++;
1027         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1028         len = 0;
1029         for (p = strings;(t = *p);p++)
1030         {
1031                 len = strlen(t);
1032                 memcpy(s, t, len);
1033                 s += len;
1034         }
1035         *s = 0;
1036         return string;
1037 }
1038
1039 static char *R_ShaderStrCat(const char **strings);
1040 static void R_InitShaderModeInfo(void)
1041 {
1042         int i, language;
1043         shadermodeinfo_t *modeinfo;
1044         // 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)
1045         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1046         {
1047                 for (i = 0; i < SHADERMODE_COUNT; i++)
1048                 {
1049                         char filename[MAX_QPATH];
1050                         modeinfo = &shadermodeinfo[language][i];
1051                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1052                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1053                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1054                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1055                 }
1056         }
1057 }
1058
1059 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1060 {
1061         char *shaderstring;
1062         // if the mode has no filename we have to return the builtin string
1063         if (builtinonly || !modeinfo->filename)
1064                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1065         // note that FS_LoadFile appends a 0 byte to make it a valid string
1066         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1067         if (shaderstring)
1068         {
1069                 if (printfromdisknotice)
1070                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1071                 return shaderstring;
1072         }
1073         // fall back to builtinstring
1074         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1075 }
1076
1077 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1078 {
1079         int i;
1080         int ubibind;
1081         int sampler;
1082         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1083         char *sourcestring;
1084         char permutationname[256];
1085         int vertstrings_count = 0;
1086         int geomstrings_count = 0;
1087         int fragstrings_count = 0;
1088         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091
1092         if (p->compiled)
1093                 return;
1094         p->compiled = true;
1095         p->program = 0;
1096
1097         permutationname[0] = 0;
1098         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1099
1100         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1101
1102         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1103         if(vid.support.glshaderversion >= 140)
1104         {
1105                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1106                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1107                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1108                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1109                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1110                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1111         }
1112         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1113         else if(vid.support.glshaderversion >= 130)
1114         {
1115                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1116                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1117                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1118                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1119                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1120                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1121         }
1122         // if we can do #version 120, we should (this adds the invariant keyword)
1123         else if(vid.support.glshaderversion >= 120)
1124         {
1125                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1126                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1127                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1128                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1129                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1130                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1131         }
1132         // GLES also adds several things from GLSL120
1133         switch(vid.renderpath)
1134         {
1135         case RENDERPATH_GLES2:
1136                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1137                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1138                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1139                 break;
1140         default:
1141                 break;
1142         }
1143
1144         // the first pretext is which type of shader to compile as
1145         // (later these will all be bound together as a program object)
1146         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1147         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1148         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1149
1150         // the second pretext is the mode (for example a light source)
1151         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1152         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1153         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1154         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1155
1156         // now add all the permutation pretexts
1157         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1158         {
1159                 if (permutation & (1ll<<i))
1160                 {
1161                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1162                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1163                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1164                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1165                 }
1166                 else
1167                 {
1168                         // keep line numbers correct
1169                         vertstrings_list[vertstrings_count++] = "\n";
1170                         geomstrings_list[geomstrings_count++] = "\n";
1171                         fragstrings_list[fragstrings_count++] = "\n";
1172                 }
1173         }
1174
1175         // add static parms
1176         R_CompileShader_AddStaticParms(mode, permutation);
1177         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         vertstrings_count += shaderstaticparms_count;
1179         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180         geomstrings_count += shaderstaticparms_count;
1181         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182         fragstrings_count += shaderstaticparms_count;
1183
1184         // now append the shader text itself
1185         vertstrings_list[vertstrings_count++] = sourcestring;
1186         geomstrings_list[geomstrings_count++] = sourcestring;
1187         fragstrings_list[fragstrings_count++] = sourcestring;
1188
1189         // compile the shader program
1190         if (vertstrings_count + geomstrings_count + fragstrings_count)
1191                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1192         if (p->program)
1193         {
1194                 CHECKGLERROR
1195                 qglUseProgram(p->program);CHECKGLERROR
1196                 // look up all the uniform variable names we care about, so we don't
1197                 // have to look them up every time we set them
1198
1199 #if 0
1200                 // debugging aid
1201                 {
1202                         GLint activeuniformindex = 0;
1203                         GLint numactiveuniforms = 0;
1204                         char uniformname[128];
1205                         GLsizei uniformnamelength = 0;
1206                         GLint uniformsize = 0;
1207                         GLenum uniformtype = 0;
1208                         memset(uniformname, 0, sizeof(uniformname));
1209                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1210                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1211                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1212                         {
1213                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1214                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1215                         }
1216                 }
1217 #endif
1218
1219                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1220                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1221                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1222                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1223                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1224                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1225                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1226                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1227                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1228                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1229                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1230                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1231                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1232                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1233                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1234                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1235                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1236                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1237                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1238                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1239                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1240                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1241                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1242                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1243                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1244                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1245                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1246                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1247                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1248                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1249                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1250                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1251                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1252                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1253                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1254                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1255                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1256                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1257                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1258                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1259                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1260                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1261                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1262                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1263                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1264                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1265                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1266                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1267                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1268                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1269                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1270                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1271                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1272                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1273                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1274                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1275                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1276                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1277                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1278                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1279                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1280                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1281                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1282                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1283                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1284                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1285                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1286                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1287                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1288                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1289                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1290                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1291                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1292                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1293                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1294                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1295                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1296                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1297                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1298                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1299                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1300                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1301                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1302                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1303                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1304                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1305                 // initialize the samplers to refer to the texture units we use
1306                 p->tex_Texture_First = -1;
1307                 p->tex_Texture_Second = -1;
1308                 p->tex_Texture_GammaRamps = -1;
1309                 p->tex_Texture_Normal = -1;
1310                 p->tex_Texture_Color = -1;
1311                 p->tex_Texture_Gloss = -1;
1312                 p->tex_Texture_Glow = -1;
1313                 p->tex_Texture_SecondaryNormal = -1;
1314                 p->tex_Texture_SecondaryColor = -1;
1315                 p->tex_Texture_SecondaryGloss = -1;
1316                 p->tex_Texture_SecondaryGlow = -1;
1317                 p->tex_Texture_Pants = -1;
1318                 p->tex_Texture_Shirt = -1;
1319                 p->tex_Texture_FogHeightTexture = -1;
1320                 p->tex_Texture_FogMask = -1;
1321                 p->tex_Texture_Lightmap = -1;
1322                 p->tex_Texture_Deluxemap = -1;
1323                 p->tex_Texture_Attenuation = -1;
1324                 p->tex_Texture_Cube = -1;
1325                 p->tex_Texture_Refraction = -1;
1326                 p->tex_Texture_Reflection = -1;
1327                 p->tex_Texture_ShadowMap2D = -1;
1328                 p->tex_Texture_CubeProjection = -1;
1329                 p->tex_Texture_ScreenNormalMap = -1;
1330                 p->tex_Texture_ScreenDiffuse = -1;
1331                 p->tex_Texture_ScreenSpecular = -1;
1332                 p->tex_Texture_ReflectMask = -1;
1333                 p->tex_Texture_ReflectCube = -1;
1334                 p->tex_Texture_BounceGrid = -1;
1335                 // bind the texture samplers in use
1336                 sampler = 0;
1337                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1338                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1339                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1340                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1341                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1342                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1343                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1344                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1345                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1346                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1347                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1348                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1349                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1350                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1351                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1352                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1353                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1354                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1355                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1356                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1357                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1358                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1359                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1360                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1361                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1362                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1363                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1364                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1365                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1366                 // get the uniform block indices so we can bind them
1367 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1368                 if (vid.support.arb_uniform_buffer_object)
1369                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1370                 else
1371 #endif
1372                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1373                 // clear the uniform block bindings
1374                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1375                 // bind the uniform blocks in use
1376                 ubibind = 0;
1377 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1378                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1379 #endif
1380                 // we're done compiling and setting up the shader, at least until it is used
1381                 CHECKGLERROR
1382                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1383         }
1384         else
1385                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1386
1387         // free the strings
1388         if (sourcestring)
1389                 Mem_Free(sourcestring);
1390 }
1391
1392 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1393 {
1394         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1395         if (r_glsl_permutation != perm)
1396         {
1397                 r_glsl_permutation = perm;
1398                 if (!r_glsl_permutation->program)
1399                 {
1400                         if (!r_glsl_permutation->compiled)
1401                         {
1402                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1403                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1404                         }
1405                         if (!r_glsl_permutation->program)
1406                         {
1407                                 // remove features until we find a valid permutation
1408                                 int i;
1409                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1410                                 {
1411                                         // reduce i more quickly whenever it would not remove any bits
1412                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1413                                         if (!(permutation & j))
1414                                                 continue;
1415                                         permutation -= j;
1416                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1417                                         if (!r_glsl_permutation->compiled)
1418                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1419                                         if (r_glsl_permutation->program)
1420                                                 break;
1421                                 }
1422                                 if (i >= SHADERPERMUTATION_COUNT)
1423                                 {
1424                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1425                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1426                                         qglUseProgram(0);CHECKGLERROR
1427                                         return; // no bit left to clear, entire mode is broken
1428                                 }
1429                         }
1430                 }
1431                 CHECKGLERROR
1432                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1433         }
1434         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1435         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1436         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1437         CHECKGLERROR
1438 }
1439
1440 #ifdef SUPPORTD3D
1441
1442 #ifdef SUPPORTD3D
1443 #include <d3d9.h>
1444 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1445 extern D3DCAPS9 vid_d3d9caps;
1446 #endif
1447
1448 struct r_hlsl_permutation_s;
1449 typedef struct r_hlsl_permutation_s
1450 {
1451         /// hash lookup data
1452         struct r_hlsl_permutation_s *hashnext;
1453         unsigned int mode;
1454         dpuint64 permutation;
1455
1456         /// indicates if we have tried compiling this permutation already
1457         qboolean compiled;
1458         /// NULL if compilation failed
1459         IDirect3DVertexShader9 *vertexshader;
1460         IDirect3DPixelShader9 *pixelshader;
1461 }
1462 r_hlsl_permutation_t;
1463
1464 typedef enum D3DVSREGISTER_e
1465 {
1466         D3DVSREGISTER_TexMatrix = 0, // float4x4
1467         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1468         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1469         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1470         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1471         D3DVSREGISTER_ModelToLight = 20, // float4x4
1472         D3DVSREGISTER_EyePosition = 24,
1473         D3DVSREGISTER_FogPlane = 25,
1474         D3DVSREGISTER_LightDir = 26,
1475         D3DVSREGISTER_LightPosition = 27,
1476 }
1477 D3DVSREGISTER_t;
1478
1479 typedef enum D3DPSREGISTER_e
1480 {
1481         D3DPSREGISTER_Alpha = 0,
1482         D3DPSREGISTER_BloomBlur_Parameters = 1,
1483         D3DPSREGISTER_ClientTime = 2,
1484         D3DPSREGISTER_Color_Ambient = 3,
1485         D3DPSREGISTER_Color_Diffuse = 4,
1486         D3DPSREGISTER_Color_Specular = 5,
1487         D3DPSREGISTER_Color_Glow = 6,
1488         D3DPSREGISTER_Color_Pants = 7,
1489         D3DPSREGISTER_Color_Shirt = 8,
1490         D3DPSREGISTER_DeferredColor_Ambient = 9,
1491         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1492         D3DPSREGISTER_DeferredColor_Specular = 11,
1493         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1494         D3DPSREGISTER_DeferredMod_Specular = 13,
1495         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1496         D3DPSREGISTER_EyePosition = 15, // unused
1497         D3DPSREGISTER_FogColor = 16,
1498         D3DPSREGISTER_FogHeightFade = 17,
1499         D3DPSREGISTER_FogPlane = 18,
1500         D3DPSREGISTER_FogPlaneViewDist = 19,
1501         D3DPSREGISTER_FogRangeRecip = 20,
1502         D3DPSREGISTER_LightColor = 21,
1503         D3DPSREGISTER_LightDir = 22, // unused
1504         D3DPSREGISTER_LightPosition = 23,
1505         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1506         D3DPSREGISTER_PixelSize = 25,
1507         D3DPSREGISTER_ReflectColor = 26,
1508         D3DPSREGISTER_ReflectFactor = 27,
1509         D3DPSREGISTER_ReflectOffset = 28,
1510         D3DPSREGISTER_RefractColor = 29,
1511         D3DPSREGISTER_Saturation = 30,
1512         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1513         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1514         D3DPSREGISTER_ScreenToDepth = 33,
1515         D3DPSREGISTER_ShadowMap_Parameters = 34,
1516         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1517         D3DPSREGISTER_SpecularPower = 36,
1518         D3DPSREGISTER_UserVec1 = 37,
1519         D3DPSREGISTER_UserVec2 = 38,
1520         D3DPSREGISTER_UserVec3 = 39,
1521         D3DPSREGISTER_UserVec4 = 40,
1522         D3DPSREGISTER_ViewTintColor = 41,
1523         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1524         D3DPSREGISTER_BloomColorSubtract = 43,
1525         D3DPSREGISTER_ViewToLight = 44, // float4x4
1526         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1527         D3DPSREGISTER_NormalmapScrollBlend = 52,
1528         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1529         D3DPSREGISTER_OffsetMapping_Bias = 54,
1530         // next at 54
1531 }
1532 D3DPSREGISTER_t;
1533
1534 /// information about each possible shader permutation
1535 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1536 /// currently selected permutation
1537 r_hlsl_permutation_t *r_hlsl_permutation;
1538 /// storage for permutations linked in the hash table
1539 memexpandablearray_t r_hlsl_permutationarray;
1540
1541 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1542 {
1543         //unsigned int hashdepth = 0;
1544         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1545         r_hlsl_permutation_t *p;
1546         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1547         {
1548                 if (p->mode == mode && p->permutation == permutation)
1549                 {
1550                         //if (hashdepth > 10)
1551                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1552                         return p;
1553                 }
1554                 //hashdepth++;
1555         }
1556         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1557         p->mode = mode;
1558         p->permutation = permutation;
1559         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1560         r_hlsl_permutationhash[mode][hashindex] = p;
1561         //if (hashdepth > 10)
1562         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1563         return p;
1564 }
1565
1566 #include <d3dx9.h>
1567 //#include <d3dx9shader.h>
1568 //#include <d3dx9mesh.h>
1569
1570 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1571 {
1572         DWORD *vsbin = NULL;
1573         DWORD *psbin = NULL;
1574         fs_offset_t vsbinsize;
1575         fs_offset_t psbinsize;
1576 //      IDirect3DVertexShader9 *vs = NULL;
1577 //      IDirect3DPixelShader9 *ps = NULL;
1578         ID3DXBuffer *vslog = NULL;
1579         ID3DXBuffer *vsbuffer = NULL;
1580         ID3DXConstantTable *vsconstanttable = NULL;
1581         ID3DXBuffer *pslog = NULL;
1582         ID3DXBuffer *psbuffer = NULL;
1583         ID3DXConstantTable *psconstanttable = NULL;
1584         int vsresult = 0;
1585         int psresult = 0;
1586         char temp[MAX_INPUTLINE];
1587         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1588         char vabuf[1024];
1589         qboolean debugshader = gl_paranoid.integer != 0;
1590         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1592         if (!debugshader)
1593         {
1594                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1595                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1596         }
1597         if ((!vsbin && vertstring) || (!psbin && fragstring))
1598         {
1599                 const char* dllnames_d3dx9 [] =
1600                 {
1601                         "d3dx9_43.dll",
1602                         "d3dx9_42.dll",
1603                         "d3dx9_41.dll",
1604                         "d3dx9_40.dll",
1605                         "d3dx9_39.dll",
1606                         "d3dx9_38.dll",
1607                         "d3dx9_37.dll",
1608                         "d3dx9_36.dll",
1609                         "d3dx9_35.dll",
1610                         "d3dx9_34.dll",
1611                         "d3dx9_33.dll",
1612                         "d3dx9_32.dll",
1613                         "d3dx9_31.dll",
1614                         "d3dx9_30.dll",
1615                         "d3dx9_29.dll",
1616                         "d3dx9_28.dll",
1617                         "d3dx9_27.dll",
1618                         "d3dx9_26.dll",
1619                         "d3dx9_25.dll",
1620                         "d3dx9_24.dll",
1621                         NULL
1622                 };
1623                 dllhandle_t d3dx9_dll = NULL;
1624                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1626                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1627                 dllfunction_t d3dx9_dllfuncs[] =
1628                 {
1629                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1630                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1631                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1632                         {NULL, NULL}
1633                 };
1634                 // 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...
1635 #ifndef ID3DXBuffer_GetBufferPointer
1636 #if !defined(__cplusplus) || defined(CINTERFACE)
1637 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1638 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1639 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1640 #else
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1643 #define ID3DXBuffer_Release(p)            (p)->Release()
1644 #endif
1645 #endif
1646                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1647                 {
1648                         DWORD shaderflags = 0;
1649                         if (debugshader)
1650                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1651                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1652                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1653                         if (vertstring && vertstring[0])
1654                         {
1655                                 if (debugshader)
1656                                 {
1657                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1658                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1659                                 }
1660                                 else
1661                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1662                                 if (vsbuffer)
1663                                 {
1664                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1665                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1666                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1667                                         ID3DXBuffer_Release(vsbuffer);
1668                                 }
1669                                 if (vslog)
1670                                 {
1671                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1672                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1673                                         ID3DXBuffer_Release(vslog);
1674                                 }
1675                         }
1676                         if (fragstring && fragstring[0])
1677                         {
1678                                 if (debugshader)
1679                                 {
1680                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1681                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1682                                 }
1683                                 else
1684                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1685                                 if (psbuffer)
1686                                 {
1687                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1688                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1689                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1690                                         ID3DXBuffer_Release(psbuffer);
1691                                 }
1692                                 if (pslog)
1693                                 {
1694                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1695                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1696                                         ID3DXBuffer_Release(pslog);
1697                                 }
1698                         }
1699                         Sys_UnloadLibrary(&d3dx9_dll);
1700                 }
1701                 else
1702                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1703         }
1704         if (vsbin && psbin)
1705         {
1706                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1707                 if (FAILED(vsresult))
1708                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1709                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1710                 if (FAILED(psresult))
1711                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1712         }
1713         // free the shader data
1714         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1715         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1716 }
1717
1718 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1719 {
1720         int i;
1721         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1722         int vertstring_length = 0;
1723         int geomstring_length = 0;
1724         int fragstring_length = 0;
1725         char *t;
1726         char *sourcestring;
1727         char *vertstring, *geomstring, *fragstring;
1728         char permutationname[256];
1729         char cachename[256];
1730         int vertstrings_count = 0;
1731         int geomstrings_count = 0;
1732         int fragstrings_count = 0;
1733         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1736
1737         if (p->compiled)
1738                 return;
1739         p->compiled = true;
1740         p->vertexshader = NULL;
1741         p->pixelshader = NULL;
1742
1743         permutationname[0] = 0;
1744         cachename[0] = 0;
1745         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1746
1747         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1748         strlcat(cachename, "hlsl/", sizeof(cachename));
1749
1750         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1751         vertstrings_count = 0;
1752         geomstrings_count = 0;
1753         fragstrings_count = 0;
1754         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1755         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1756         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1757
1758         // the first pretext is which type of shader to compile as
1759         // (later these will all be bound together as a program object)
1760         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1761         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1762         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1763
1764         // the second pretext is the mode (for example a light source)
1765         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1766         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1767         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1768         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1769         strlcat(cachename, modeinfo->name, sizeof(cachename));
1770
1771         // now add all the permutation pretexts
1772         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1773         {
1774                 if (permutation & (1ll<<i))
1775                 {
1776                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1777                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1778                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1779                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1780                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1781                 }
1782                 else
1783                 {
1784                         // keep line numbers correct
1785                         vertstrings_list[vertstrings_count++] = "\n";
1786                         geomstrings_list[geomstrings_count++] = "\n";
1787                         fragstrings_list[fragstrings_count++] = "\n";
1788                 }
1789         }
1790
1791         // add static parms
1792         R_CompileShader_AddStaticParms(mode, permutation);
1793         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         vertstrings_count += shaderstaticparms_count;
1795         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796         geomstrings_count += shaderstaticparms_count;
1797         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798         fragstrings_count += shaderstaticparms_count;
1799
1800         // replace spaces in the cachename with _ characters
1801         for (i = 0;cachename[i];i++)
1802                 if (cachename[i] == ' ')
1803                         cachename[i] = '_';
1804
1805         // now append the shader text itself
1806         vertstrings_list[vertstrings_count++] = sourcestring;
1807         geomstrings_list[geomstrings_count++] = sourcestring;
1808         fragstrings_list[fragstrings_count++] = sourcestring;
1809
1810         vertstring_length = 0;
1811         for (i = 0;i < vertstrings_count;i++)
1812                 vertstring_length += (int)strlen(vertstrings_list[i]);
1813         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1814         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1815                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1816
1817         geomstring_length = 0;
1818         for (i = 0;i < geomstrings_count;i++)
1819                 geomstring_length += (int)strlen(geomstrings_list[i]);
1820         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1821         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1822                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1823
1824         fragstring_length = 0;
1825         for (i = 0;i < fragstrings_count;i++)
1826                 fragstring_length += (int)strlen(fragstrings_list[i]);
1827         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1828         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1829                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1830
1831         // try to load the cached shader, or generate one
1832         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1833
1834         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1835                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1836         else
1837                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1838
1839         // free the strings
1840         if (vertstring)
1841                 Mem_Free(vertstring);
1842         if (geomstring)
1843                 Mem_Free(geomstring);
1844         if (fragstring)
1845                 Mem_Free(fragstring);
1846         if (sourcestring)
1847                 Mem_Free(sourcestring);
1848 }
1849
1850 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1851 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1852 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);}
1853 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);}
1854 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);}
1855 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);}
1856
1857 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1858 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1859 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);}
1860 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);}
1861 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);}
1862 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);}
1863
1864 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1865 {
1866         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1867         if (r_hlsl_permutation != perm)
1868         {
1869                 r_hlsl_permutation = perm;
1870                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1871                 {
1872                         if (!r_hlsl_permutation->compiled)
1873                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1874                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875                         {
1876                                 // remove features until we find a valid permutation
1877                                 int i;
1878                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879                                 {
1880                                         // reduce i more quickly whenever it would not remove any bits
1881                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1882                                         if (!(permutation & j))
1883                                                 continue;
1884                                         permutation -= j;
1885                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1886                                         if (!r_hlsl_permutation->compiled)
1887                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1888                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1889                                                 break;
1890                                 }
1891                                 if (i >= SHADERPERMUTATION_COUNT)
1892                                 {
1893                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1894                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1895                                         return; // no bit left to clear, entire mode is broken
1896                                 }
1897                         }
1898                 }
1899                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1900                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1901         }
1902         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1903         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1904         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1905 }
1906 #endif
1907
1908 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1909 {
1910         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1911         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1912         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1913         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1914 }
1915
1916 void R_GLSL_Restart_f(void)
1917 {
1918         unsigned int i, limit;
1919         switch(vid.renderpath)
1920         {
1921         case RENDERPATH_D3D9:
1922 #ifdef SUPPORTD3D
1923                 {
1924                         r_hlsl_permutation_t *p;
1925                         r_hlsl_permutation = NULL;
1926                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1927                         for (i = 0;i < limit;i++)
1928                         {
1929                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1930                                 {
1931                                         if (p->vertexshader)
1932                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1933                                         if (p->pixelshader)
1934                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1935                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1936                                 }
1937                         }
1938                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1939                 }
1940 #endif
1941                 break;
1942         case RENDERPATH_D3D10:
1943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_D3D11:
1946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947                 break;
1948         case RENDERPATH_GL20:
1949         case RENDERPATH_GLES2:
1950                 {
1951                         r_glsl_permutation_t *p;
1952                         r_glsl_permutation = NULL;
1953                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1954                         for (i = 0;i < limit;i++)
1955                         {
1956                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1957                                 {
1958                                         GL_Backend_FreeProgram(p->program);
1959                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1960                                 }
1961                         }
1962                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1963                 }
1964                 break;
1965         case RENDERPATH_GL11:
1966         case RENDERPATH_GL13:
1967         case RENDERPATH_GLES1:
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 break;
1971         }
1972 }
1973
1974 static void R_GLSL_DumpShader_f(void)
1975 {
1976         int i, language, mode, dupe;
1977         char *text;
1978         shadermodeinfo_t *modeinfo;
1979         qfile_t *file;
1980
1981         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1982         {
1983                 modeinfo = shadermodeinfo[language];
1984                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1985                 {
1986                         // don't dump the same file multiple times (most or all shaders come from the same file)
1987                         for (dupe = mode - 1;dupe >= 0;dupe--)
1988                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1989                                         break;
1990                         if (dupe >= 0)
1991                                 continue;
1992                         text = modeinfo[mode].builtinstring;
1993                         if (!text)
1994                                 continue;
1995                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1996                         if (file)
1997                         {
1998                                 FS_Print(file, "/* The engine may define the following macros:\n");
1999                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2000                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2001                                         FS_Print(file, modeinfo[i].pretext);
2002                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2003                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2004                                 FS_Print(file, "*/\n");
2005                                 FS_Print(file, text);
2006                                 FS_Close(file);
2007                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2008                         }
2009                         else
2010                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2011                 }
2012         }
2013 }
2014
2015 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2016 {
2017         dpuint64 permutation = 0;
2018         if (r_trippy.integer && !notrippy)
2019                 permutation |= SHADERPERMUTATION_TRIPPY;
2020         permutation |= SHADERPERMUTATION_VIEWTINT;
2021         if (first)
2022                 permutation |= SHADERPERMUTATION_DIFFUSE;
2023         if (second)
2024                 permutation |= SHADERPERMUTATION_SPECULAR;
2025         if (texturemode == GL_MODULATE)
2026                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2027         else if (texturemode == GL_ADD)
2028                 permutation |= SHADERPERMUTATION_GLOW;
2029         else if (texturemode == GL_DECAL)
2030                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2031         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2032                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2033         if (suppresstexalpha)
2034                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2035         if (!second)
2036                 texturemode = GL_MODULATE;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTD3D
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2044                 R_Mesh_TexBind(GL20TU_FIRST , first );
2045                 R_Mesh_TexBind(GL20TU_SECOND, second);
2046                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2047                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2048 #endif
2049                 break;
2050         case RENDERPATH_D3D10:
2051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052                 break;
2053         case RENDERPATH_D3D11:
2054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2055                 break;
2056         case RENDERPATH_GL20:
2057         case RENDERPATH_GLES2:
2058                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2059                 if (r_glsl_permutation->tex_Texture_First >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2061                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2062                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2063                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2064                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2065                 break;
2066         case RENDERPATH_GL13:
2067         case RENDERPATH_GLES1:
2068                 R_Mesh_TexBind(0, first );
2069                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2070                 R_Mesh_TexMatrix(0, NULL);
2071                 R_Mesh_TexBind(1, second);
2072                 if (second)
2073                 {
2074                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2075                         R_Mesh_TexMatrix(1, NULL);
2076                 }
2077                 break;
2078         case RENDERPATH_GL11:
2079                 R_Mesh_TexBind(0, first );
2080                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2081                 R_Mesh_TexMatrix(0, NULL);
2082                 break;
2083         case RENDERPATH_SOFT:
2084                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2085                 R_Mesh_TexBind(GL20TU_FIRST , first );
2086                 R_Mesh_TexBind(GL20TU_SECOND, second);
2087                 break;
2088         }
2089 }
2090
2091 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2092 {
2093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2094 }
2095
2096 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2097 {
2098         dpuint64 permutation = 0;
2099         if (r_trippy.integer && !notrippy)
2100                 permutation |= SHADERPERMUTATION_TRIPPY;
2101         if (depthrgb)
2102                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2103         if (skeletal)
2104                 permutation |= SHADERPERMUTATION_SKELETAL;
2105
2106         if (vid.allowalphatocoverage)
2107                 GL_AlphaToCoverage(false);
2108         switch (vid.renderpath)
2109         {
2110         case RENDERPATH_D3D9:
2111 #ifdef SUPPORTD3D
2112                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2113 #endif
2114                 break;
2115         case RENDERPATH_D3D10:
2116                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2117                 break;
2118         case RENDERPATH_D3D11:
2119                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2120                 break;
2121         case RENDERPATH_GL20:
2122         case RENDERPATH_GLES2:
2123                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2124 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2125                 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);
2126 #endif
2127                 break;
2128         case RENDERPATH_GL13:
2129         case RENDERPATH_GLES1:
2130                 R_Mesh_TexBind(0, 0);
2131                 R_Mesh_TexBind(1, 0);
2132                 break;
2133         case RENDERPATH_GL11:
2134                 R_Mesh_TexBind(0, 0);
2135                 break;
2136         case RENDERPATH_SOFT:
2137                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2138                 break;
2139         }
2140 }
2141
2142 extern qboolean r_shadow_usingdeferredprepass;
2143 extern rtexture_t *r_shadow_attenuationgradienttexture;
2144 extern rtexture_t *r_shadow_attenuation2dtexture;
2145 extern rtexture_t *r_shadow_attenuation3dtexture;
2146 extern qboolean r_shadow_usingshadowmap2d;
2147 extern qboolean r_shadow_usingshadowmaportho;
2148 extern float r_shadow_modelshadowmap_texturescale[4];
2149 extern float r_shadow_modelshadowmap_parameters[4];
2150 extern float r_shadow_lightshadowmap_texturescale[4];
2151 extern float r_shadow_lightshadowmap_parameters[4];
2152 extern qboolean r_shadow_shadowmapvsdct;
2153 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2154 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2155 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2156 extern matrix4x4_t r_shadow_shadowmapmatrix;
2157 extern int r_shadow_prepass_width;
2158 extern int r_shadow_prepass_height;
2159 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2160 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2161 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2162 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2163
2164 #define BLENDFUNC_ALLOWS_COLORMOD      1
2165 #define BLENDFUNC_ALLOWS_FOG           2
2166 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2167 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2168 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2169 static int R_BlendFuncFlags(int src, int dst)
2170 {
2171         int r = 0;
2172
2173         // a blendfunc allows colormod if:
2174         // a) it can never keep the destination pixel invariant, or
2175         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2176         // this is to prevent unintended side effects from colormod
2177
2178         // a blendfunc allows fog if:
2179         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2180         // this is to prevent unintended side effects from fog
2181
2182         // these checks are the output of fogeval.pl
2183
2184         r |= BLENDFUNC_ALLOWS_COLORMOD;
2185         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2189         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2194         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2196         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2198         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2201         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2202         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2205         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206
2207         return r;
2208 }
2209
2210 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2211 {
2212         // select a permutation of the lighting shader appropriate to this
2213         // combination of texture, entity, light source, and fogging, only use the
2214         // minimum features necessary to avoid wasting rendering time in the
2215         // fragment shader on features that are not being used
2216         dpuint64 permutation = 0;
2217         unsigned int mode = 0;
2218         int blendfuncflags;
2219         static float dummy_colormod[3] = {1, 1, 1};
2220         float *colormod = rsurface.colormod;
2221         float m16f[16];
2222         matrix4x4_t tempmatrix;
2223         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2224         if (r_trippy.integer && !notrippy)
2225                 permutation |= SHADERPERMUTATION_TRIPPY;
2226         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2227                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2228         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2229                 permutation |= SHADERPERMUTATION_OCCLUDE;
2230         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2231                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2232         if (rsurfacepass == RSURFPASS_BACKGROUND)
2233         {
2234                 // distorted background
2235                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2236                 {
2237                         mode = SHADERMODE_WATER;
2238                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2239                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2240                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2241                         {
2242                                 // this is the right thing to do for wateralpha
2243                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2244                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2245                         }
2246                         else
2247                         {
2248                                 // this is the right thing to do for entity alpha
2249                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2251                         }
2252                 }
2253                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2254                 {
2255                         mode = SHADERMODE_REFRACTION;
2256                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2257                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2258                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2260                 }
2261                 else
2262                 {
2263                         mode = SHADERMODE_GENERIC;
2264                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2265                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2267                 }
2268                 if (vid.allowalphatocoverage)
2269                         GL_AlphaToCoverage(false);
2270         }
2271         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2272         {
2273                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2274                 {
2275                         switch(rsurface.texture->offsetmapping)
2276                         {
2277                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2278                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2280                         case OFFSETMAPPING_OFF: break;
2281                         }
2282                 }
2283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285                 // normalmap (deferred prepass), may use alpha test on diffuse
2286                 mode = SHADERMODE_DEFERREDGEOMETRY;
2287                 GL_BlendFunc(GL_ONE, GL_ZERO);
2288                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2289                 if (vid.allowalphatocoverage)
2290                         GL_AlphaToCoverage(false);
2291         }
2292         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2293         {
2294                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2295                 {
2296                         switch(rsurface.texture->offsetmapping)
2297                         {
2298                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_OFF: break;
2302                         }
2303                 }
2304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2307                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2308                 // light source
2309                 mode = SHADERMODE_LIGHTSOURCE;
2310                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2311                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2312                 if (diffusescale > 0)
2313                         permutation |= SHADERPERMUTATION_DIFFUSE;
2314                 if (specularscale > 0)
2315                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2316                 if (r_refdef.fogenabled)
2317                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2318                 if (rsurface.texture->colormapping)
2319                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2320                 if (r_shadow_usingshadowmap2d)
2321                 {
2322                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323                         if(r_shadow_shadowmapvsdct)
2324                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2325
2326                         if (r_shadow_shadowmap2ddepthbuffer)
2327                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2328                 }
2329                 if (rsurface.texture->reflectmasktexture)
2330                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2331                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2332                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2333                 if (vid.allowalphatocoverage)
2334                         GL_AlphaToCoverage(false);
2335         }
2336         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2337         {
2338                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2339                 {
2340                         switch(rsurface.texture->offsetmapping)
2341                         {
2342                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_OFF: break;
2346                         }
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2351                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2352                 // unshaded geometry (fullbright or ambient model lighting)
2353                 mode = SHADERMODE_FLATCOLOR;
2354                 ambientscale = diffusescale = specularscale = 0;
2355                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2356                         permutation |= SHADERPERMUTATION_GLOW;
2357                 if (r_refdef.fogenabled)
2358                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2359                 if (rsurface.texture->colormapping)
2360                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2361                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2362                 {
2363                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2364                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2365
2366                         if (r_shadow_shadowmap2ddepthbuffer)
2367                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2368                 }
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370                         permutation |= SHADERPERMUTATION_REFLECTION;
2371                 if (rsurface.texture->reflectmasktexture)
2372                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2373                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2375                 // when using alphatocoverage, we don't need alphakill
2376                 if (vid.allowalphatocoverage)
2377                 {
2378                         if (r_transparent_alphatocoverage.integer)
2379                         {
2380                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2381                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2382                         }
2383                         else
2384                                 GL_AlphaToCoverage(false);
2385                 }
2386         }
2387         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2388         {
2389                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2390                 {
2391                         switch(rsurface.texture->offsetmapping)
2392                         {
2393                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2394                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2396                         case OFFSETMAPPING_OFF: break;
2397                         }
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2402                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2403                 // directional model lighting
2404                 mode = SHADERMODE_LIGHTDIRECTION;
2405                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2406                         permutation |= SHADERPERMUTATION_GLOW;
2407                 permutation |= SHADERPERMUTATION_DIFFUSE;
2408                 if (specularscale > 0)
2409                         permutation |= SHADERPERMUTATION_SPECULAR;
2410                 if (r_refdef.fogenabled)
2411                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2412                 if (rsurface.texture->colormapping)
2413                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2414                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2415                 {
2416                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2417                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2418
2419                         if (r_shadow_shadowmap2ddepthbuffer)
2420                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2421                 }
2422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2423                         permutation |= SHADERPERMUTATION_REFLECTION;
2424                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2425                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2426                 if (rsurface.texture->reflectmasktexture)
2427                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2428                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2429                 {
2430                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2431                         if (r_shadow_bouncegrid_state.directional)
2432                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2433                 }
2434                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436                 // when using alphatocoverage, we don't need alphakill
2437                 if (vid.allowalphatocoverage)
2438                 {
2439                         if (r_transparent_alphatocoverage.integer)
2440                         {
2441                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2442                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2443                         }
2444                         else
2445                                 GL_AlphaToCoverage(false);
2446                 }
2447         }
2448         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2449         {
2450                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2451                 {
2452                         switch(rsurface.texture->offsetmapping)
2453                         {
2454                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2455                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2457                         case OFFSETMAPPING_OFF: break;
2458                         }
2459                 }
2460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2463                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2464                 // ambient model lighting
2465                 mode = SHADERMODE_LIGHTDIRECTION;
2466                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2467                         permutation |= SHADERPERMUTATION_GLOW;
2468                 if (r_refdef.fogenabled)
2469                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2470                 if (rsurface.texture->colormapping)
2471                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2472                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2473                 {
2474                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2475                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2476
2477                         if (r_shadow_shadowmap2ddepthbuffer)
2478                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2479                 }
2480                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2481                         permutation |= SHADERPERMUTATION_REFLECTION;
2482                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2483                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2484                 if (rsurface.texture->reflectmasktexture)
2485                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2486                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2487                 {
2488                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489                         if (r_shadow_bouncegrid_state.directional)
2490                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2491                 }
2492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 // when using alphatocoverage, we don't need alphakill
2495                 if (vid.allowalphatocoverage)
2496                 {
2497                         if (r_transparent_alphatocoverage.integer)
2498                         {
2499                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2501                         }
2502                         else
2503                                 GL_AlphaToCoverage(false);
2504                 }
2505         }
2506         else
2507         {
2508                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2509                 {
2510                         switch(rsurface.texture->offsetmapping)
2511                         {
2512                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2513                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2514                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2515                         case OFFSETMAPPING_OFF: break;
2516                         }
2517                 }
2518                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2519                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2520                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2521                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2522                 // lightmapped wall
2523                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2524                         permutation |= SHADERPERMUTATION_GLOW;
2525                 if (r_refdef.fogenabled)
2526                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2527                 if (rsurface.texture->colormapping)
2528                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2529                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2530                 {
2531                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2532                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2533
2534                         if (r_shadow_shadowmap2ddepthbuffer)
2535                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2536                 }
2537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2538                         permutation |= SHADERPERMUTATION_REFLECTION;
2539                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2540                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2541                 if (rsurface.texture->reflectmasktexture)
2542                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2543                 if (FAKELIGHT_ENABLED)
2544                 {
2545                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2546                         mode = SHADERMODE_FAKELIGHT;
2547                         permutation |= SHADERPERMUTATION_DIFFUSE;
2548                         if (specularscale > 0)
2549                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2550                 }
2551                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2552                 {
2553                         // deluxemapping (light direction texture)
2554                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2555                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2556                         else
2557                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2558                         permutation |= SHADERPERMUTATION_DIFFUSE;
2559                         if (specularscale > 0)
2560                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2561                 }
2562                 else if (r_glsl_deluxemapping.integer >= 2)
2563                 {
2564                         // fake deluxemapping (uniform light direction in tangentspace)
2565                         if (rsurface.uselightmaptexture)
2566                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2567                         else
2568                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2569                         permutation |= SHADERPERMUTATION_DIFFUSE;
2570                         if (specularscale > 0)
2571                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2572                 }
2573                 else if (rsurface.uselightmaptexture)
2574                 {
2575                         // ordinary lightmapping (q1bsp, q3bsp)
2576                         mode = SHADERMODE_LIGHTMAP;
2577                 }
2578                 else
2579                 {
2580                         // ordinary vertex coloring (q3bsp)
2581                         mode = SHADERMODE_VERTEXCOLOR;
2582                 }
2583                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2584                 {
2585                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2586                         if (r_shadow_bouncegrid_state.directional)
2587                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2588                 }
2589                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2590                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2591                 // when using alphatocoverage, we don't need alphakill
2592                 if (vid.allowalphatocoverage)
2593                 {
2594                         if (r_transparent_alphatocoverage.integer)
2595                         {
2596                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2597                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2598                         }
2599                         else
2600                                 GL_AlphaToCoverage(false);
2601                 }
2602         }
2603         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2604                 colormod = dummy_colormod;
2605         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2606                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2607         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2608                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2609         switch(vid.renderpath)
2610         {
2611         case RENDERPATH_D3D9:
2612 #ifdef SUPPORTD3D
2613                 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);
2614                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2615                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2616                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2617                 if (mode == SHADERMODE_LIGHTSOURCE)
2618                 {
2619                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2620                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2621                 }
2622                 else
2623                 {
2624                         if (mode == SHADERMODE_LIGHTDIRECTION)
2625                         {
2626                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2627                         }
2628                 }
2629                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2630                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2631                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2632                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2634
2635                 if (mode == SHADERMODE_LIGHTSOURCE)
2636                 {
2637                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2638                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2639                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2641                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2642
2643                         // additive passes are only darkened by fog, not tinted
2644                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2645                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2646                 }
2647                 else
2648                 {
2649                         if (mode == SHADERMODE_FLATCOLOR)
2650                         {
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2652                         }
2653                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2654                         {
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2661                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2662                         }
2663                         else
2664                         {
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2666                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2667                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2668                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2669                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2670                         }
2671                         // additive passes are only darkened by fog, not tinted
2672                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2673                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2674                         else
2675                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2676                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2677                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2678                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2679                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2680                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2681                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2682                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2683                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2684                         if (mode == SHADERMODE_WATER)
2685                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2686                 }
2687                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2688                 {
2689                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2690                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2691                 }
2692                 else
2693                 {
2694                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2695                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2696                 }
2697                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2698                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2699                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2700                 if (rsurface.texture->pantstexture)
2701                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2702                 else
2703                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2704                 if (rsurface.texture->shirttexture)
2705                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2706                 else
2707                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2708                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2709                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2710                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2711                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2712                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2713                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2714                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2716                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2717                         );
2718                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2719                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2720                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2721                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2722
2723                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2724                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2725                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2726                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2727                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2728                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2729                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2730                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2731                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2732                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2733                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2734                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2735                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2736                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2737                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2738                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2739                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2740                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2741                 {
2742                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2743                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2744                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2745                 }
2746                 else
2747                 {
2748                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2749                 }
2750 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2751                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2752                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2753                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2754                 {
2755                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2756                         if (rsurface.rtlight)
2757                         {
2758                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2759                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2760                         }
2761                 }
2762 #endif
2763                 break;
2764         case RENDERPATH_D3D10:
2765                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2766                 break;
2767         case RENDERPATH_D3D11:
2768                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2769                 break;
2770         case RENDERPATH_GL20:
2771         case RENDERPATH_GLES2:
2772                 if (!vid.useinterleavedarrays)
2773                 {
2774                         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);
2775                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2776                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2777                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2778                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2779                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2780                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2781                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2782                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2783                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2784                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2785                 }
2786                 else
2787                 {
2788                         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);
2789                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2790                 }
2791                 // this has to be after RSurf_PrepareVerticesForBatch
2792                 if (rsurface.batchskeletaltransform3x4buffer)
2793                         permutation |= SHADERPERMUTATION_SKELETAL;
2794                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2795 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2796                 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);
2797 #endif
2798                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2799                 if (mode == SHADERMODE_LIGHTSOURCE)
2800                 {
2801                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2802                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2803                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2804                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2805                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2806                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2807         
2808                         // additive passes are only darkened by fog, not tinted
2809                         if (r_glsl_permutation->loc_FogColor >= 0)
2810                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2811                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2812                 }
2813                 else
2814                 {
2815                         if (mode == SHADERMODE_FLATCOLOR)
2816                         {
2817                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2818                         }
2819                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2820                         {
2821                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2822                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2823                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2824                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2825                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2826                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2827                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2828                         }
2829                         else
2830                         {
2831                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2832                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2833                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2834                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2836                         }
2837                         // additive passes are only darkened by fog, not tinted
2838                         if (r_glsl_permutation->loc_FogColor >= 0)
2839                         {
2840                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2841                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2842                                 else
2843                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2844                         }
2845                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2846                         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]);
2847                         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]);
2848                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2849                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2850                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2851                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2852                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2853                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2854                 }
2855                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2856                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2857                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2858                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2859                 {
2860                         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]);
2861                         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]);
2862                 }
2863                 else
2864                 {
2865                         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]);
2866                         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]);
2867                 }
2868
2869                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2870                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2871                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2872                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2873                 {
2874                         if (rsurface.texture->pantstexture)
2875                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2876                         else
2877                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2878                 }
2879                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2880                 {
2881                         if (rsurface.texture->shirttexture)
2882                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2883                         else
2884                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2885                 }
2886                 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]);
2887                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2888                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2889                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2890                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2891                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2892                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2893                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2894                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2895                         );
2896                 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);
2897                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2898                 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]);
2899                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2900                 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);}
2901                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2902
2903                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2904                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2905                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2906                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2907                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2908                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2909                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2910                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2911                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2912                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2913                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2914                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2915                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2916                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2917                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2918                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2919                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2920                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2921                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2922                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2923                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2924                 {
2925                         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);
2926                         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);
2927                         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);
2928                 }
2929                 else
2930                 {
2931                         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);
2932                 }
2933                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2934                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2935                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2936                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2937                 {
2938                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2939                         if (rsurface.rtlight)
2940                         {
2941                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2942                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2943                         }
2944                 }
2945                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2946                 CHECKGLERROR
2947                 break;
2948         case RENDERPATH_GL11:
2949         case RENDERPATH_GL13:
2950         case RENDERPATH_GLES1:
2951                 break;
2952         case RENDERPATH_SOFT:
2953                 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);
2954                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2955                 R_SetupShader_SetPermutationSoft(mode, permutation);
2956                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2957                 if (mode == SHADERMODE_LIGHTSOURCE)
2958                 {
2959                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2960                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2961                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2962                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2963                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2964                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2965         
2966                         // additive passes are only darkened by fog, not tinted
2967                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2968                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2969                 }
2970                 else
2971                 {
2972                         if (mode == SHADERMODE_FLATCOLOR)
2973                         {
2974                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2975                         }
2976                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2977                         {
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2979                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2981                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2982                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2984                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2985                         }
2986                         else
2987                         {
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2989                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2990                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2991                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2992                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2993                         }
2994                         // additive passes are only darkened by fog, not tinted
2995                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2996                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2997                         else
2998                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2999                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
3000                         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]);
3001                         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]);
3002                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3003                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3004                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3005                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3006                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3007                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3008                 }
3009                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3010                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3011                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3012                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3013                 {
3014                         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]);
3015                         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]);
3016                 }
3017                 else
3018                 {
3019                         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]);
3020                         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]);
3021                 }
3022
3023                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3024                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3025                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3026                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3027                 {
3028                         if (rsurface.texture->pantstexture)
3029                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3030                         else
3031                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3032                 }
3033                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3034                 {
3035                         if (rsurface.texture->shirttexture)
3036                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3037                         else
3038                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3039                 }
3040                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3041                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3042                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3043                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3044                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3045                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3046                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3047                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3048                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3049                         );
3050                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3051                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3052                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3054
3055                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3056                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3057                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3058                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3059                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3060                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3061                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3062                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3063                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3064                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3065                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3066                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3067                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3068                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3069                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3070                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3071                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3072                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3073                 {
3074                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3075                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3076                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3077                 }
3078                 else
3079                 {
3080                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3081                 }
3082 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3083                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3084                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3085                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3086                 {
3087                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3088                         if (rsurface.rtlight)
3089                         {
3090                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3091                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3092                         }
3093                 }
3094                 break;
3095         }
3096 }
3097
3098 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3099 {
3100         // select a permutation of the lighting shader appropriate to this
3101         // combination of texture, entity, light source, and fogging, only use the
3102         // minimum features necessary to avoid wasting rendering time in the
3103         // fragment shader on features that are not being used
3104         dpuint64 permutation = 0;
3105         unsigned int mode = 0;
3106         const float *lightcolorbase = rtlight->currentcolor;
3107         float ambientscale = rtlight->ambientscale;
3108         float diffusescale = rtlight->diffusescale;
3109         float specularscale = rtlight->specularscale;
3110         // this is the location of the light in view space
3111         vec3_t viewlightorigin;
3112         // this transforms from view space (camera) to light space (cubemap)
3113         matrix4x4_t viewtolight;
3114         matrix4x4_t lighttoview;
3115         float viewtolight16f[16];
3116         // light source
3117         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3118         if (rtlight->currentcubemap != r_texture_whitecube)
3119                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3120         if (diffusescale > 0)
3121                 permutation |= SHADERPERMUTATION_DIFFUSE;
3122         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3123                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3124         if (r_shadow_usingshadowmap2d)
3125         {
3126                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3127                 if (r_shadow_shadowmapvsdct)
3128                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3129
3130                 if (r_shadow_shadowmap2ddepthbuffer)
3131                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3132         }
3133         if (vid.allowalphatocoverage)
3134                 GL_AlphaToCoverage(false);
3135         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3136         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3137         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3138         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3139         switch(vid.renderpath)
3140         {
3141         case RENDERPATH_D3D9:
3142 #ifdef SUPPORTD3D
3143                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3144                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3145                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3146                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3147                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3148                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3149                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3150                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3151                 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);
3152                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3153                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3154
3155                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3156                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3157                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3158                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3159                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3160 #endif
3161                 break;
3162         case RENDERPATH_D3D10:
3163                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3164                 break;
3165         case RENDERPATH_D3D11:
3166                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3167                 break;
3168         case RENDERPATH_GL20:
3169         case RENDERPATH_GLES2:
3170                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3171                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3172                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3173                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3174                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3175                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3176                 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]);
3177                 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]);
3178                 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);
3179                 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]);
3180                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3181
3182                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3183                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3184                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3185                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3186                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3187                 break;
3188         case RENDERPATH_GL11:
3189         case RENDERPATH_GL13:
3190         case RENDERPATH_GLES1:
3191                 break;
3192         case RENDERPATH_SOFT:
3193                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3194                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3195                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3196                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3197                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3198                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3199                 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]);
3200                 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]);
3201                 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);
3202                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3203                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3204
3205                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3206                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3207                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3208                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3209                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3210                 break;
3211         }
3212 }
3213
3214 #define SKINFRAME_HASH 1024
3215
3216 typedef struct
3217 {
3218         unsigned int loadsequence; // incremented each level change
3219         memexpandablearray_t array;
3220         skinframe_t *hash[SKINFRAME_HASH];
3221 }
3222 r_skinframe_t;
3223 r_skinframe_t r_skinframe;
3224
3225 void R_SkinFrame_PrepareForPurge(void)
3226 {
3227         r_skinframe.loadsequence++;
3228         // wrap it without hitting zero
3229         if (r_skinframe.loadsequence >= 200)
3230                 r_skinframe.loadsequence = 1;
3231 }
3232
3233 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3234 {
3235         if (!skinframe)
3236                 return;
3237         // mark the skinframe as used for the purging code
3238         skinframe->loadsequence = r_skinframe.loadsequence;
3239 }
3240
3241 void R_SkinFrame_Purge(void)
3242 {
3243         int i;
3244         skinframe_t *s;
3245         for (i = 0;i < SKINFRAME_HASH;i++)
3246         {
3247                 for (s = r_skinframe.hash[i];s;s = s->next)
3248                 {
3249                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3250                         {
3251                                 if (s->merged == s->base)
3252                                         s->merged = NULL;
3253                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3254                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3255                                 R_PurgeTexture(s->merged);s->merged = NULL;
3256                                 R_PurgeTexture(s->base  );s->base   = NULL;
3257                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3258                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3259                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3260                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3261                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3262                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3263                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3264                                 s->loadsequence = 0;
3265                         }
3266                 }
3267         }
3268 }
3269
3270 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3271         skinframe_t *item;
3272         char basename[MAX_QPATH];
3273
3274         Image_StripImageExtension(name, basename, sizeof(basename));
3275
3276         if( last == NULL ) {
3277                 int hashindex;
3278                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3279                 item = r_skinframe.hash[hashindex];
3280         } else {
3281                 item = last->next;
3282         }
3283
3284         // linearly search through the hash bucket
3285         for( ; item ; item = item->next ) {
3286                 if( !strcmp( item->basename, basename ) ) {
3287                         return item;
3288                 }
3289         }
3290         return NULL;
3291 }
3292
3293 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3294 {
3295         skinframe_t *item;
3296         int hashindex;
3297         char basename[MAX_QPATH];
3298
3299         Image_StripImageExtension(name, basename, sizeof(basename));
3300
3301         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3302         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3303                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3304                         break;
3305
3306         if (!item) {
3307                 rtexture_t *dyntexture;
3308                 // check whether its a dynamic texture
3309                 dyntexture = CL_GetDynTexture( basename );
3310                 if (!add && !dyntexture)
3311                         return NULL;
3312                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3313                 memset(item, 0, sizeof(*item));
3314                 strlcpy(item->basename, basename, sizeof(item->basename));
3315                 item->base = dyntexture; // either NULL or dyntexture handle
3316                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3317                 item->comparewidth = comparewidth;
3318                 item->compareheight = compareheight;
3319                 item->comparecrc = comparecrc;
3320                 item->next = r_skinframe.hash[hashindex];
3321                 r_skinframe.hash[hashindex] = item;
3322         }
3323         else if (textureflags & TEXF_FORCE_RELOAD)
3324         {
3325                 rtexture_t *dyntexture;
3326                 // check whether its a dynamic texture
3327                 dyntexture = CL_GetDynTexture( basename );
3328                 if (!add && !dyntexture)
3329                         return NULL;
3330                 if (item->merged == item->base)
3331                         item->merged = NULL;
3332                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3333                 R_PurgeTexture(item->stain );item->stain  = NULL;
3334                 R_PurgeTexture(item->merged);item->merged = NULL;
3335                 R_PurgeTexture(item->base  );item->base   = NULL;
3336                 R_PurgeTexture(item->pants );item->pants  = NULL;
3337                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3338                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3339                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3340                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3341                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3342         R_PurgeTexture(item->reflect);item->reflect = NULL;
3343                 item->loadsequence = 0;
3344         }
3345         else if( item->base == NULL )
3346         {
3347                 rtexture_t *dyntexture;
3348                 // check whether its a dynamic texture
3349                 // 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]
3350                 dyntexture = CL_GetDynTexture( basename );
3351                 item->base = dyntexture; // either NULL or dyntexture handle
3352         }
3353
3354         R_SkinFrame_MarkUsed(item);
3355         return item;
3356 }
3357
3358 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3359         { \
3360                 unsigned long long avgcolor[5], wsum; \
3361                 int pix, comp, w; \
3362                 avgcolor[0] = 0; \
3363                 avgcolor[1] = 0; \
3364                 avgcolor[2] = 0; \
3365                 avgcolor[3] = 0; \
3366                 avgcolor[4] = 0; \
3367                 wsum = 0; \
3368                 for(pix = 0; pix < cnt; ++pix) \
3369                 { \
3370                         w = 0; \
3371                         for(comp = 0; comp < 3; ++comp) \
3372                                 w += getpixel; \
3373                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3374                         { \
3375                                 ++wsum; \
3376                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3377                                 w = getpixel; \
3378                                 for(comp = 0; comp < 3; ++comp) \
3379                                         avgcolor[comp] += getpixel * w; \
3380                                 avgcolor[3] += w; \
3381                         } \
3382                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3383                         avgcolor[4] += getpixel; \
3384                 } \
3385                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3386                         avgcolor[3] = 1; \
3387                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3388                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3389                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3390                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3391         }
3392
3393 extern cvar_t gl_picmip;
3394 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3395 {
3396         int j;
3397         unsigned char *pixels;
3398         unsigned char *bumppixels;
3399         unsigned char *basepixels = NULL;
3400         int basepixels_width = 0;
3401         int basepixels_height = 0;
3402         skinframe_t *skinframe;
3403         rtexture_t *ddsbase = NULL;
3404         qboolean ddshasalpha = false;
3405         float ddsavgcolor[4];
3406         char basename[MAX_QPATH];
3407         int miplevel = R_PicmipForFlags(textureflags);
3408         int savemiplevel = miplevel;
3409         int mymiplevel;
3410         char vabuf[1024];
3411
3412         if (cls.state == ca_dedicated)
3413                 return NULL;
3414
3415         // return an existing skinframe if already loaded
3416         // if loading of the first image fails, don't make a new skinframe as it
3417         // would cause all future lookups of this to be missing
3418         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3419         if (skinframe && skinframe->base)
3420                 return skinframe;
3421
3422         Image_StripImageExtension(name, basename, sizeof(basename));
3423
3424         // check for DDS texture file first
3425         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3426         {
3427                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3428                 if (basepixels == NULL)
3429                         return NULL;
3430         }
3431
3432         // FIXME handle miplevel
3433
3434         if (developer_loading.integer)
3435                 Con_Printf("loading skin \"%s\"\n", name);
3436
3437         // we've got some pixels to store, so really allocate this new texture now
3438         if (!skinframe)
3439                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3440         textureflags &= ~TEXF_FORCE_RELOAD;
3441         skinframe->stain = NULL;
3442         skinframe->merged = NULL;
3443         skinframe->base = NULL;
3444         skinframe->pants = NULL;
3445         skinframe->shirt = NULL;
3446         skinframe->nmap = NULL;
3447         skinframe->gloss = NULL;
3448         skinframe->glow = NULL;
3449         skinframe->fog = NULL;
3450         skinframe->reflect = NULL;
3451         skinframe->hasalpha = false;
3452         // we could store the q2animname here too
3453
3454         if (ddsbase)
3455         {
3456                 skinframe->base = ddsbase;
3457                 skinframe->hasalpha = ddshasalpha;
3458                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3459                 if (r_loadfog && skinframe->hasalpha)
3460                         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);
3461                 //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]);
3462         }
3463         else
3464         {
3465                 basepixels_width = image_width;
3466                 basepixels_height = image_height;
3467                 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);
3468                 if (textureflags & TEXF_ALPHA)
3469                 {
3470                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3471                         {
3472                                 if (basepixels[j] < 255)
3473                                 {
3474                                         skinframe->hasalpha = true;
3475                                         break;
3476                                 }
3477                         }
3478                         if (r_loadfog && skinframe->hasalpha)
3479                         {
3480                                 // has transparent pixels
3481                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3482                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3483                                 {
3484                                         pixels[j+0] = 255;
3485                                         pixels[j+1] = 255;
3486                                         pixels[j+2] = 255;
3487                                         pixels[j+3] = basepixels[j+3];
3488                                 }
3489                                 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);
3490                                 Mem_Free(pixels);
3491                         }
3492                 }
3493                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3494 #ifndef USE_GLES2
3495                 //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]);
3496                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3497                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3498                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3499                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3500 #endif
3501         }
3502
3503         if (r_loaddds)
3504         {
3505                 mymiplevel = savemiplevel;
3506                 if (r_loadnormalmap)
3507                         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);
3508                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3509                 if (r_loadgloss)
3510                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3511                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3512                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3513                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3514         }
3515
3516         // _norm is the name used by tenebrae and has been adopted as standard
3517         if (r_loadnormalmap && skinframe->nmap == NULL)
3518         {
3519                 mymiplevel = savemiplevel;
3520                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3521                 {
3522                         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);
3523                         Mem_Free(pixels);
3524                         pixels = NULL;
3525                 }
3526                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3527                 {
3528                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3529                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3530                         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);
3531                         Mem_Free(pixels);
3532                         Mem_Free(bumppixels);
3533                 }
3534                 else if (r_shadow_bumpscale_basetexture.value > 0)
3535                 {
3536                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3537                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3538                         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);
3539                         Mem_Free(pixels);
3540                 }
3541 #ifndef USE_GLES2
3542                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3543                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3544 #endif
3545         }
3546
3547         // _luma is supported only for tenebrae compatibility
3548         // _glow is the preferred name
3549         mymiplevel = savemiplevel;
3550         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3551         {
3552                 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);
3553 #ifndef USE_GLES2
3554                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3555                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3556 #endif
3557                 Mem_Free(pixels);pixels = NULL;
3558         }
3559
3560         mymiplevel = savemiplevel;
3561         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3562         {
3563                 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);
3564 #ifndef USE_GLES2
3565                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3566                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3567 #endif
3568                 Mem_Free(pixels);
3569                 pixels = NULL;
3570         }
3571
3572         mymiplevel = savemiplevel;
3573         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3574         {
3575                 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);
3576 #ifndef USE_GLES2
3577                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3578                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3579 #endif
3580                 Mem_Free(pixels);
3581                 pixels = NULL;
3582         }
3583
3584         mymiplevel = savemiplevel;
3585         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3586         {
3587                 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);
3588 #ifndef USE_GLES2
3589                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3590                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3591 #endif
3592                 Mem_Free(pixels);
3593                 pixels = NULL;
3594         }
3595
3596         mymiplevel = savemiplevel;
3597         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3598         {
3599                 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);
3600 #ifndef USE_GLES2
3601                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3602                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3603 #endif
3604                 Mem_Free(pixels);
3605                 pixels = NULL;
3606         }
3607
3608         if (basepixels)
3609                 Mem_Free(basepixels);
3610
3611         return skinframe;
3612 }
3613
3614 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3615 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3616 {
3617         int i;
3618         skinframe_t *skinframe;
3619         char vabuf[1024];
3620
3621         if (cls.state == ca_dedicated)
3622                 return NULL;
3623
3624         // if already loaded just return it, otherwise make a new skinframe
3625         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3626         if (skinframe->base)
3627                 return skinframe;
3628         textureflags &= ~TEXF_FORCE_RELOAD;
3629
3630         skinframe->stain = NULL;
3631         skinframe->merged = NULL;
3632         skinframe->base = NULL;
3633         skinframe->pants = NULL;
3634         skinframe->shirt = NULL;
3635         skinframe->nmap = NULL;
3636         skinframe->gloss = NULL;
3637         skinframe->glow = NULL;
3638         skinframe->fog = NULL;
3639         skinframe->reflect = NULL;
3640         skinframe->hasalpha = false;
3641
3642         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3643         if (!skindata)
3644                 return NULL;
3645
3646         if (developer_loading.integer)
3647                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3648
3649         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3650         {
3651                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3652                 unsigned char *b = a + width * height * 4;
3653                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3654                 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);
3655                 Mem_Free(a);
3656         }
3657         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3658         if (textureflags & TEXF_ALPHA)
3659         {
3660                 for (i = 3;i < width * height * 4;i += 4)
3661                 {
3662                         if (skindata[i] < 255)
3663                         {
3664                                 skinframe->hasalpha = true;
3665                                 break;
3666                         }
3667                 }
3668                 if (r_loadfog && skinframe->hasalpha)
3669                 {
3670                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3671                         memcpy(fogpixels, skindata, width * height * 4);
3672                         for (i = 0;i < width * height * 4;i += 4)
3673                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3674                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3675                         Mem_Free(fogpixels);
3676                 }
3677         }
3678
3679         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3680         //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]);
3681
3682         return skinframe;
3683 }
3684
3685 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3686 {
3687         int i;
3688         int featuresmask;
3689         skinframe_t *skinframe;
3690
3691         if (cls.state == ca_dedicated)
3692                 return NULL;
3693
3694         // if already loaded just return it, otherwise make a new skinframe
3695         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3696         if (skinframe->base)
3697                 return skinframe;
3698         //textureflags &= ~TEXF_FORCE_RELOAD;
3699
3700         skinframe->stain = NULL;
3701         skinframe->merged = NULL;
3702         skinframe->base = NULL;
3703         skinframe->pants = NULL;
3704         skinframe->shirt = NULL;
3705         skinframe->nmap = NULL;
3706         skinframe->gloss = NULL;
3707         skinframe->glow = NULL;
3708         skinframe->fog = NULL;
3709         skinframe->reflect = NULL;
3710         skinframe->hasalpha = false;
3711
3712         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3713         if (!skindata)
3714                 return NULL;
3715
3716         if (developer_loading.integer)
3717                 Con_Printf("loading quake skin \"%s\"\n", name);
3718
3719         // 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)
3720         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3721         memcpy(skinframe->qpixels, skindata, width*height);
3722         skinframe->qwidth = width;
3723         skinframe->qheight = height;
3724
3725         featuresmask = 0;
3726         for (i = 0;i < width * height;i++)
3727                 featuresmask |= palette_featureflags[skindata[i]];
3728
3729         skinframe->hasalpha = false;
3730         // fence textures
3731         if (name[0] == '{')
3732                 skinframe->hasalpha = true;
3733         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3734         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3735         skinframe->qgeneratemerged = true;
3736         skinframe->qgeneratebase = skinframe->qhascolormapping;
3737         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3738
3739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3740         //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]);
3741
3742         return skinframe;
3743 }
3744
3745 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3746 {
3747         int width;
3748         int height;
3749         unsigned char *skindata;
3750         char vabuf[1024];
3751
3752         if (!skinframe->qpixels)
3753                 return;
3754
3755         if (!skinframe->qhascolormapping)
3756                 colormapped = false;
3757
3758         if (colormapped)
3759         {
3760                 if (!skinframe->qgeneratebase)
3761                         return;
3762         }
3763         else
3764         {
3765                 if (!skinframe->qgeneratemerged)
3766                         return;
3767         }
3768
3769         width = skinframe->qwidth;
3770         height = skinframe->qheight;
3771         skindata = skinframe->qpixels;
3772
3773         if (skinframe->qgeneratenmap)
3774         {
3775                 unsigned char *a, *b;
3776                 skinframe->qgeneratenmap = false;
3777                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3778                 b = a + width * height * 4;
3779                 // use either a custom palette or the quake palette
3780                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3781                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3782                 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);
3783                 Mem_Free(a);
3784         }
3785
3786         if (skinframe->qgenerateglow)
3787         {
3788                 skinframe->qgenerateglow = false;
3789                 if (skinframe->hasalpha) // fence textures
3790                         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
3791                 else
3792                         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
3793         }
3794
3795         if (colormapped)
3796         {
3797                 skinframe->qgeneratebase = false;
3798                 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);
3799                 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);
3800                 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);
3801         }
3802         else
3803         {
3804                 skinframe->qgeneratemerged = false;
3805                 if (skinframe->hasalpha) // fence textures
3806                         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);
3807                 else
3808                         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);
3809         }
3810
3811         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3812         {
3813                 Mem_Free(skinframe->qpixels);
3814                 skinframe->qpixels = NULL;
3815         }
3816 }
3817
3818 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)
3819 {
3820         int i;
3821         skinframe_t *skinframe;
3822         char vabuf[1024];
3823
3824         if (cls.state == ca_dedicated)
3825                 return NULL;
3826
3827         // if already loaded just return it, otherwise make a new skinframe
3828         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3829         if (skinframe->base)
3830                 return skinframe;
3831         textureflags &= ~TEXF_FORCE_RELOAD;
3832
3833         skinframe->stain = NULL;
3834         skinframe->merged = NULL;
3835         skinframe->base = NULL;
3836         skinframe->pants = NULL;
3837         skinframe->shirt = NULL;
3838         skinframe->nmap = NULL;
3839         skinframe->gloss = NULL;
3840         skinframe->glow = NULL;
3841         skinframe->fog = NULL;
3842         skinframe->reflect = NULL;
3843         skinframe->hasalpha = false;
3844
3845         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3846         if (!skindata)
3847                 return NULL;
3848
3849         if (developer_loading.integer)
3850                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3851
3852         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3853         if (textureflags & TEXF_ALPHA)
3854         {
3855                 for (i = 0;i < width * height;i++)
3856                 {
3857                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3858                         {
3859                                 skinframe->hasalpha = true;
3860                                 break;
3861                         }
3862                 }
3863                 if (r_loadfog && skinframe->hasalpha)
3864                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3865         }
3866
3867         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3868         //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]);
3869
3870         return skinframe;
3871 }
3872
3873 skinframe_t *R_SkinFrame_LoadMissing(void)
3874 {
3875         skinframe_t *skinframe;
3876
3877         if (cls.state == ca_dedicated)
3878                 return NULL;
3879
3880         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3881         skinframe->stain = NULL;
3882         skinframe->merged = NULL;
3883         skinframe->base = NULL;
3884         skinframe->pants = NULL;
3885         skinframe->shirt = NULL;
3886         skinframe->nmap = NULL;
3887         skinframe->gloss = NULL;
3888         skinframe->glow = NULL;
3889         skinframe->fog = NULL;
3890         skinframe->reflect = NULL;
3891         skinframe->hasalpha = false;
3892
3893         skinframe->avgcolor[0] = rand() / RAND_MAX;
3894         skinframe->avgcolor[1] = rand() / RAND_MAX;
3895         skinframe->avgcolor[2] = rand() / RAND_MAX;
3896         skinframe->avgcolor[3] = 1;
3897
3898         return skinframe;
3899 }
3900
3901 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3902 typedef struct suffixinfo_s
3903 {
3904         const char *suffix;
3905         qboolean flipx, flipy, flipdiagonal;
3906 }
3907 suffixinfo_t;
3908 static suffixinfo_t suffix[3][6] =
3909 {
3910         {
3911                 {"px",   false, false, false},
3912                 {"nx",   false, false, false},
3913                 {"py",   false, false, false},
3914                 {"ny",   false, false, false},
3915                 {"pz",   false, false, false},
3916                 {"nz",   false, false, false}
3917         },
3918         {
3919                 {"posx", false, false, false},
3920                 {"negx", false, false, false},
3921                 {"posy", false, false, false},
3922                 {"negy", false, false, false},
3923                 {"posz", false, false, false},
3924                 {"negz", false, false, false}
3925         },
3926         {
3927                 {"rt",    true, false,  true},
3928                 {"lf",   false,  true,  true},
3929                 {"ft",    true,  true, false},
3930                 {"bk",   false, false, false},
3931                 {"up",    true, false,  true},
3932                 {"dn",    true, false,  true}
3933         }
3934 };
3935
3936 static int componentorder[4] = {0, 1, 2, 3};
3937
3938 static rtexture_t *R_LoadCubemap(const char *basename)
3939 {
3940         int i, j, cubemapsize;
3941         unsigned char *cubemappixels, *image_buffer;
3942         rtexture_t *cubemaptexture;
3943         char name[256];
3944         // must start 0 so the first loadimagepixels has no requested width/height
3945         cubemapsize = 0;
3946         cubemappixels = NULL;
3947         cubemaptexture = NULL;
3948         // keep trying different suffix groups (posx, px, rt) until one loads
3949         for (j = 0;j < 3 && !cubemappixels;j++)
3950         {
3951                 // load the 6 images in the suffix group
3952                 for (i = 0;i < 6;i++)
3953                 {
3954                         // generate an image name based on the base and and suffix
3955                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3956                         // load it
3957                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3958                         {
3959                                 // an image loaded, make sure width and height are equal
3960                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3961                                 {
3962                                         // if this is the first image to load successfully, allocate the cubemap memory
3963                                         if (!cubemappixels && image_width >= 1)
3964                                         {
3965                                                 cubemapsize = image_width;
3966                                                 // note this clears to black, so unavailable sides are black
3967                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3968                                         }
3969                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3970                                         if (cubemappixels)
3971                                                 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);
3972                                 }
3973                                 else
3974                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3975                                 // free the image
3976                                 Mem_Free(image_buffer);
3977                         }
3978                 }
3979         }
3980         // if a cubemap loaded, upload it
3981         if (cubemappixels)
3982         {
3983                 if (developer_loading.integer)
3984                         Con_Printf("loading cubemap \"%s\"\n", basename);
3985
3986                 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);
3987                 Mem_Free(cubemappixels);
3988         }
3989         else
3990         {
3991                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3992                 if (developer_loading.integer)
3993                 {
3994                         Con_Printf("(tried tried images ");
3995                         for (j = 0;j < 3;j++)
3996                                 for (i = 0;i < 6;i++)
3997                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3998                         Con_Print(" and was unable to find any of them).\n");
3999                 }
4000         }
4001         return cubemaptexture;
4002 }
4003
4004 rtexture_t *R_GetCubemap(const char *basename)
4005 {
4006         int i;
4007         for (i = 0;i < r_texture_numcubemaps;i++)
4008                 if (r_texture_cubemaps[i] != NULL)
4009                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4010                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4011         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4012                 return r_texture_whitecube;
4013         r_texture_numcubemaps++;
4014         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4015         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4016         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4017         return r_texture_cubemaps[i]->texture;
4018 }
4019
4020 static void R_Main_FreeViewCache(void)
4021 {
4022         if (r_refdef.viewcache.entityvisible)
4023                 Mem_Free(r_refdef.viewcache.entityvisible);
4024         if (r_refdef.viewcache.world_pvsbits)
4025                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4026         if (r_refdef.viewcache.world_leafvisible)
4027                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4028         if (r_refdef.viewcache.world_surfacevisible)
4029                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4030         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4031 }
4032
4033 static void R_Main_ResizeViewCache(void)
4034 {
4035         int numentities = r_refdef.scene.numentities;
4036         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4037         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4038         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4039         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4040         if (r_refdef.viewcache.maxentities < numentities)
4041         {
4042                 r_refdef.viewcache.maxentities = numentities;
4043                 if (r_refdef.viewcache.entityvisible)
4044                         Mem_Free(r_refdef.viewcache.entityvisible);
4045                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4046         }
4047         if (r_refdef.viewcache.world_numclusters != numclusters)
4048         {
4049                 r_refdef.viewcache.world_numclusters = numclusters;
4050                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4051                 if (r_refdef.viewcache.world_pvsbits)
4052                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4053                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4054         }
4055         if (r_refdef.viewcache.world_numleafs != numleafs)
4056         {
4057                 r_refdef.viewcache.world_numleafs = numleafs;
4058                 if (r_refdef.viewcache.world_leafvisible)
4059                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4060                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4061         }
4062         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4063         {
4064                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4065                 if (r_refdef.viewcache.world_surfacevisible)
4066                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4067                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4068         }
4069 }
4070
4071 extern rtexture_t *loadingscreentexture;
4072 static void gl_main_start(void)
4073 {
4074         loadingscreentexture = NULL;
4075         r_texture_blanknormalmap = NULL;
4076         r_texture_white = NULL;
4077         r_texture_grey128 = NULL;
4078         r_texture_black = NULL;
4079         r_texture_whitecube = NULL;
4080         r_texture_normalizationcube = NULL;
4081         r_texture_fogattenuation = NULL;
4082         r_texture_fogheighttexture = NULL;
4083         r_texture_gammaramps = NULL;
4084         r_texture_numcubemaps = 0;
4085         r_uniformbufferalignment = 32;
4086
4087         r_loaddds = r_texture_dds_load.integer != 0;
4088         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL20:
4093         case RENDERPATH_D3D9:
4094         case RENDERPATH_D3D10:
4095         case RENDERPATH_D3D11:
4096         case RENDERPATH_SOFT:
4097         case RENDERPATH_GLES2:
4098                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4099                 Cvar_SetValueQuick(&gl_combine, 1);
4100                 Cvar_SetValueQuick(&r_glsl, 1);
4101                 r_loadnormalmap = true;
4102                 r_loadgloss = true;
4103                 r_loadfog = false;
4104 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4105                 if (vid.support.arb_uniform_buffer_object)
4106                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4107 #endif
4108                         break;
4109         case RENDERPATH_GL13:
4110         case RENDERPATH_GLES1:
4111                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4112                 Cvar_SetValueQuick(&gl_combine, 1);
4113                 Cvar_SetValueQuick(&r_glsl, 0);
4114                 r_loadnormalmap = false;
4115                 r_loadgloss = false;
4116                 r_loadfog = true;
4117                 break;
4118         case RENDERPATH_GL11:
4119                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4120                 Cvar_SetValueQuick(&gl_combine, 0);
4121                 Cvar_SetValueQuick(&r_glsl, 0);
4122                 r_loadnormalmap = false;
4123                 r_loadgloss = false;
4124                 r_loadfog = true;
4125                 break;
4126         }
4127
4128         R_AnimCache_Free();
4129         R_FrameData_Reset();
4130         R_BufferData_Reset();
4131
4132         r_numqueries = 0;
4133         r_maxqueries = 0;
4134         memset(r_queries, 0, sizeof(r_queries));
4135
4136         r_qwskincache = NULL;
4137         r_qwskincache_size = 0;
4138
4139         // due to caching of texture_t references, the collision cache must be reset
4140         Collision_Cache_Reset(true);
4141
4142         // set up r_skinframe loading system for textures
4143         memset(&r_skinframe, 0, sizeof(r_skinframe));
4144         r_skinframe.loadsequence = 1;
4145         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4146
4147         r_main_texturepool = R_AllocTexturePool();
4148         R_BuildBlankTextures();
4149         R_BuildNoTexture();
4150         if (vid.support.arb_texture_cube_map)
4151         {
4152                 R_BuildWhiteCube();
4153                 R_BuildNormalizationCube();
4154         }
4155         r_texture_fogattenuation = NULL;
4156         r_texture_fogheighttexture = NULL;
4157         r_texture_gammaramps = NULL;
4158         //r_texture_fogintensity = NULL;
4159         memset(&r_fb, 0, sizeof(r_fb));
4160         r_glsl_permutation = NULL;
4161         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4162         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4163 #ifdef SUPPORTD3D
4164         r_hlsl_permutation = NULL;
4165         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4166         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4167 #endif
4168         memset(&r_svbsp, 0, sizeof (r_svbsp));
4169
4170         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4171         r_texture_numcubemaps = 0;
4172
4173         r_refdef.fogmasktable_density = 0;
4174
4175 #ifdef __ANDROID__
4176         // For Steelstorm Android
4177         // FIXME CACHE the program and reload
4178         // FIXME see possible combinations for SS:BR android
4179         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4180         R_SetupShader_SetPermutationGLSL(0, 12);
4181         R_SetupShader_SetPermutationGLSL(0, 13);
4182         R_SetupShader_SetPermutationGLSL(0, 8388621);
4183         R_SetupShader_SetPermutationGLSL(3, 0);
4184         R_SetupShader_SetPermutationGLSL(3, 2048);
4185         R_SetupShader_SetPermutationGLSL(5, 0);
4186         R_SetupShader_SetPermutationGLSL(5, 2);
4187         R_SetupShader_SetPermutationGLSL(5, 2048);
4188         R_SetupShader_SetPermutationGLSL(5, 8388608);
4189         R_SetupShader_SetPermutationGLSL(11, 1);
4190         R_SetupShader_SetPermutationGLSL(11, 2049);
4191         R_SetupShader_SetPermutationGLSL(11, 8193);
4192         R_SetupShader_SetPermutationGLSL(11, 10241);
4193         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4194 #endif
4195 }
4196
4197 static void gl_main_shutdown(void)
4198 {
4199         R_AnimCache_Free();
4200         R_FrameData_Reset();
4201         R_BufferData_Reset();
4202
4203         R_Main_FreeViewCache();
4204
4205         switch(vid.renderpath)
4206         {
4207         case RENDERPATH_GL11:
4208         case RENDERPATH_GL13:
4209         case RENDERPATH_GL20:
4210         case RENDERPATH_GLES1:
4211         case RENDERPATH_GLES2:
4212 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4213                 if (r_maxqueries)
4214                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4215 #endif
4216                 break;
4217         case RENDERPATH_D3D9:
4218                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4219                 break;
4220         case RENDERPATH_D3D10:
4221                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4222                 break;
4223         case RENDERPATH_D3D11:
4224                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4225                 break;
4226         case RENDERPATH_SOFT:
4227                 break;
4228         }
4229
4230         r_numqueries = 0;
4231         r_maxqueries = 0;
4232         memset(r_queries, 0, sizeof(r_queries));
4233
4234         r_qwskincache = NULL;
4235         r_qwskincache_size = 0;
4236
4237         // clear out the r_skinframe state
4238         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4239         memset(&r_skinframe, 0, sizeof(r_skinframe));
4240
4241         if (r_svbsp.nodes)
4242                 Mem_Free(r_svbsp.nodes);
4243         memset(&r_svbsp, 0, sizeof (r_svbsp));
4244         R_FreeTexturePool(&r_main_texturepool);
4245         loadingscreentexture = NULL;
4246         r_texture_blanknormalmap = NULL;
4247         r_texture_white = NULL;
4248         r_texture_grey128 = NULL;
4249         r_texture_black = NULL;
4250         r_texture_whitecube = NULL;
4251         r_texture_normalizationcube = NULL;
4252         r_texture_fogattenuation = NULL;
4253         r_texture_fogheighttexture = NULL;
4254         r_texture_gammaramps = NULL;
4255         r_texture_numcubemaps = 0;
4256         //r_texture_fogintensity = NULL;
4257         memset(&r_fb, 0, sizeof(r_fb));
4258         R_GLSL_Restart_f();
4259
4260         r_glsl_permutation = NULL;
4261         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4262         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4263 #ifdef SUPPORTD3D
4264         r_hlsl_permutation = NULL;
4265         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4266         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4267 #endif
4268 }
4269
4270 static void gl_main_newmap(void)
4271 {
4272         // FIXME: move this code to client
4273         char *entities, entname[MAX_QPATH];
4274         if (r_qwskincache)
4275                 Mem_Free(r_qwskincache);
4276         r_qwskincache = NULL;
4277         r_qwskincache_size = 0;
4278         if (cl.worldmodel)
4279         {
4280                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4281                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4282                 {
4283                         CL_ParseEntityLump(entities);
4284                         Mem_Free(entities);
4285                         return;
4286                 }
4287                 if (cl.worldmodel->brush.entities)
4288                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4289         }
4290         R_Main_FreeViewCache();
4291
4292         R_FrameData_Reset();
4293         R_BufferData_Reset();
4294 }
4295
4296 void GL_Main_Init(void)
4297 {
4298         int i;
4299         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4300         R_InitShaderModeInfo();
4301
4302         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4303         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4304         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4305         if (gamemode == GAME_NEHAHRA)
4306         {
4307                 Cvar_RegisterVariable (&gl_fogenable);
4308                 Cvar_RegisterVariable (&gl_fogdensity);
4309                 Cvar_RegisterVariable (&gl_fogred);
4310                 Cvar_RegisterVariable (&gl_foggreen);
4311                 Cvar_RegisterVariable (&gl_fogblue);
4312                 Cvar_RegisterVariable (&gl_fogstart);
4313                 Cvar_RegisterVariable (&gl_fogend);
4314                 Cvar_RegisterVariable (&gl_skyclip);
4315         }
4316         Cvar_RegisterVariable(&r_motionblur);
4317         Cvar_RegisterVariable(&r_damageblur);
4318         Cvar_RegisterVariable(&r_motionblur_averaging);
4319         Cvar_RegisterVariable(&r_motionblur_randomize);
4320         Cvar_RegisterVariable(&r_motionblur_minblur);
4321         Cvar_RegisterVariable(&r_motionblur_maxblur);
4322         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4323         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4324         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4325         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4326         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4327         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4328         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4329         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4330         Cvar_RegisterVariable(&r_equalize_entities_by);
4331         Cvar_RegisterVariable(&r_equalize_entities_to);
4332         Cvar_RegisterVariable(&r_depthfirst);
4333         Cvar_RegisterVariable(&r_useinfinitefarclip);
4334         Cvar_RegisterVariable(&r_farclip_base);
4335         Cvar_RegisterVariable(&r_farclip_world);
4336         Cvar_RegisterVariable(&r_nearclip);
4337         Cvar_RegisterVariable(&r_deformvertexes);
4338         Cvar_RegisterVariable(&r_transparent);
4339         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4340         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4341         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4342         Cvar_RegisterVariable(&r_showoverdraw);
4343         Cvar_RegisterVariable(&r_showbboxes);
4344         Cvar_RegisterVariable(&r_showbboxes_client);
4345         Cvar_RegisterVariable(&r_showsurfaces);
4346         Cvar_RegisterVariable(&r_showtris);
4347         Cvar_RegisterVariable(&r_shownormals);
4348         Cvar_RegisterVariable(&r_showlighting);
4349         Cvar_RegisterVariable(&r_showshadowvolumes);
4350         Cvar_RegisterVariable(&r_showcollisionbrushes);
4351         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4352         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4353         Cvar_RegisterVariable(&r_showdisabledepthtest);
4354         Cvar_RegisterVariable(&r_drawportals);
4355         Cvar_RegisterVariable(&r_drawentities);
4356         Cvar_RegisterVariable(&r_draw2d);
4357         Cvar_RegisterVariable(&r_drawworld);
4358         Cvar_RegisterVariable(&r_cullentities_trace);
4359         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4360         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4361         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4362         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4363         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4364         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4365         Cvar_RegisterVariable(&r_sortentities);
4366         Cvar_RegisterVariable(&r_drawviewmodel);
4367         Cvar_RegisterVariable(&r_drawexteriormodel);
4368         Cvar_RegisterVariable(&r_speeds);
4369         Cvar_RegisterVariable(&r_fullbrights);
4370         Cvar_RegisterVariable(&r_wateralpha);
4371         Cvar_RegisterVariable(&r_dynamic);
4372         Cvar_RegisterVariable(&r_fakelight);
4373         Cvar_RegisterVariable(&r_fakelight_intensity);
4374         Cvar_RegisterVariable(&r_fullbright);
4375         Cvar_RegisterVariable(&r_shadows);
4376         Cvar_RegisterVariable(&r_shadows_darken);
4377         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4378         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4379         Cvar_RegisterVariable(&r_shadows_throwdistance);
4380         Cvar_RegisterVariable(&r_shadows_throwdirection);
4381         Cvar_RegisterVariable(&r_shadows_focus);
4382         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4383         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4384         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4385         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4386         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4387         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4388         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4389         Cvar_RegisterVariable(&r_fog_exp2);
4390         Cvar_RegisterVariable(&r_fog_clear);
4391         Cvar_RegisterVariable(&r_drawfog);
4392         Cvar_RegisterVariable(&r_transparentdepthmasking);
4393         Cvar_RegisterVariable(&r_transparent_sortmindist);
4394         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4395         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4396         Cvar_RegisterVariable(&r_texture_dds_load);
4397         Cvar_RegisterVariable(&r_texture_dds_save);
4398         Cvar_RegisterVariable(&r_textureunits);
4399         Cvar_RegisterVariable(&gl_combine);
4400         Cvar_RegisterVariable(&r_usedepthtextures);
4401         Cvar_RegisterVariable(&r_viewfbo);
4402         Cvar_RegisterVariable(&r_viewscale);
4403         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4404         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4405         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4406         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4407         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4408         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4409         Cvar_RegisterVariable(&r_glsl);
4410         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4412         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4413         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4414         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4415         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4416         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4417         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4418         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4419         Cvar_RegisterVariable(&r_glsl_postprocess);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4421         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4422         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4427         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4428         Cvar_RegisterVariable(&r_celshading);
4429         Cvar_RegisterVariable(&r_celoutlines);
4430
4431         Cvar_RegisterVariable(&r_water);
4432         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4433         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4434         Cvar_RegisterVariable(&r_water_clippingplanebias);
4435         Cvar_RegisterVariable(&r_water_refractdistort);
4436         Cvar_RegisterVariable(&r_water_reflectdistort);
4437         Cvar_RegisterVariable(&r_water_scissormode);
4438         Cvar_RegisterVariable(&r_water_lowquality);
4439         Cvar_RegisterVariable(&r_water_hideplayer);
4440         Cvar_RegisterVariable(&r_water_fbo);
4441
4442         Cvar_RegisterVariable(&r_lerpsprites);
4443         Cvar_RegisterVariable(&r_lerpmodels);
4444         Cvar_RegisterVariable(&r_lerplightstyles);
4445         Cvar_RegisterVariable(&r_waterscroll);
4446         Cvar_RegisterVariable(&r_bloom);
4447         Cvar_RegisterVariable(&r_bloom_colorscale);
4448         Cvar_RegisterVariable(&r_bloom_brighten);
4449         Cvar_RegisterVariable(&r_bloom_blur);
4450         Cvar_RegisterVariable(&r_bloom_resolution);
4451         Cvar_RegisterVariable(&r_bloom_colorexponent);
4452         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4453         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4454         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4455         Cvar_RegisterVariable(&r_hdr_glowintensity);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4457         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4458         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4459         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4460         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4461         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4462         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4463         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4464         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4465         Cvar_RegisterVariable(&developer_texturelogging);
4466         Cvar_RegisterVariable(&gl_lightmaps);
4467         Cvar_RegisterVariable(&r_test);
4468         Cvar_RegisterVariable(&r_batch_multidraw);
4469         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4470         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4471         Cvar_RegisterVariable(&r_glsl_skeletal);
4472         Cvar_RegisterVariable(&r_glsl_saturation);
4473         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4474         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4475         Cvar_RegisterVariable(&r_framedatasize);
4476         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4477                 Cvar_RegisterVariable(&r_buffermegs[i]);
4478         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4479         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4480                 Cvar_SetValue("r_fullbrights", 0);
4481 #ifdef DP_MOBILETOUCH
4482         // GLES devices have terrible depth precision in general, so...
4483         Cvar_SetValueQuick(&r_nearclip, 4);
4484         Cvar_SetValueQuick(&r_farclip_base, 4096);
4485         Cvar_SetValueQuick(&r_farclip_world, 0);
4486         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4487 #endif
4488         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4489 }
4490
4491 void Render_Init(void)
4492 {
4493         gl_backend_init();
4494         R_Textures_Init();
4495         GL_Main_Init();
4496         Font_Init();
4497         GL_Draw_Init();
4498         R_Shadow_Init();
4499         R_Sky_Init();
4500         GL_Surf_Init();
4501         Sbar_Init();
4502         R_Particles_Init();
4503         R_Explosion_Init();
4504         R_LightningBeams_Init();
4505         Mod_RenderInit();
4506 }
4507
4508 /*
4509 ===============
4510 GL_Init
4511 ===============
4512 */
4513 #ifndef USE_GLES2
4514 extern char *ENGINE_EXTENSIONS;
4515 void GL_Init (void)
4516 {
4517         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4518         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4519         gl_version = (const char *)qglGetString(GL_VERSION);
4520         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4521
4522         if (!gl_extensions)
4523                 gl_extensions = "";
4524         if (!gl_platformextensions)
4525                 gl_platformextensions = "";
4526
4527         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4528         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4529         Con_Printf("GL_VERSION: %s\n", gl_version);
4530         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4531         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4532
4533         VID_CheckExtensions();
4534
4535         // LordHavoc: report supported extensions
4536 #ifdef CONFIG_MENU
4537         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4538 #else
4539         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4540 #endif
4541
4542         // clear to black (loading plaque will be seen over this)
4543         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4544 }
4545 #endif
4546
4547 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4548 {
4549         int i;
4550         mplane_t *p;
4551         if (r_trippy.integer)
4552                 return false;
4553         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4554         {
4555                 p = r_refdef.view.frustum + i;
4556                 switch(p->signbits)
4557                 {
4558                 default:
4559                 case 0:
4560                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4561                                 return true;
4562                         break;
4563                 case 1:
4564                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4565                                 return true;
4566                         break;
4567                 case 2:
4568                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4569                                 return true;
4570                         break;
4571                 case 3:
4572                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4573                                 return true;
4574                         break;
4575                 case 4:
4576                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4577                                 return true;
4578                         break;
4579                 case 5:
4580                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4581                                 return true;
4582                         break;
4583                 case 6:
4584                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585                                 return true;
4586                         break;
4587                 case 7:
4588                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4589                                 return true;
4590                         break;
4591                 }
4592         }
4593         return false;
4594 }
4595
4596 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4597 {
4598         int i;
4599         const mplane_t *p;
4600         if (r_trippy.integer)
4601                 return false;
4602         for (i = 0;i < numplanes;i++)
4603         {
4604                 p = planes + i;
4605                 switch(p->signbits)
4606                 {
4607                 default:
4608                 case 0:
4609                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4610                                 return true;
4611                         break;
4612                 case 1:
4613                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4614                                 return true;
4615                         break;
4616                 case 2:
4617                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4618                                 return true;
4619                         break;
4620                 case 3:
4621                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4622                                 return true;
4623                         break;
4624                 case 4:
4625                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4626                                 return true;
4627                         break;
4628                 case 5:
4629                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4630                                 return true;
4631                         break;
4632                 case 6:
4633                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4634                                 return true;
4635                         break;
4636                 case 7:
4637                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4638                                 return true;
4639                         break;
4640                 }
4641         }
4642         return false;
4643 }
4644
4645 //==================================================================================
4646
4647 // LordHavoc: this stores temporary data used within the same frame
4648
4649 typedef struct r_framedata_mem_s
4650 {
4651         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4652         size_t size; // how much usable space
4653         size_t current; // how much space in use
4654         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4655         size_t wantedsize; // how much space was allocated
4656         unsigned char *data; // start of real data (16byte aligned)
4657 }
4658 r_framedata_mem_t;
4659
4660 static r_framedata_mem_t *r_framedata_mem;
4661
4662 void R_FrameData_Reset(void)
4663 {
4664         while (r_framedata_mem)
4665         {
4666                 r_framedata_mem_t *next = r_framedata_mem->purge;
4667                 Mem_Free(r_framedata_mem);
4668                 r_framedata_mem = next;
4669         }
4670 }
4671
4672 static void R_FrameData_Resize(qboolean mustgrow)
4673 {
4674         size_t wantedsize;
4675         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4676         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4677         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4678         {
4679                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4680                 newmem->wantedsize = wantedsize;
4681                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4682                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4683                 newmem->current = 0;
4684                 newmem->mark = 0;
4685                 newmem->purge = r_framedata_mem;
4686                 r_framedata_mem = newmem;
4687         }
4688 }
4689
4690 void R_FrameData_NewFrame(void)
4691 {
4692         R_FrameData_Resize(false);
4693         if (!r_framedata_mem)
4694                 return;
4695         // if we ran out of space on the last frame, free the old memory now
4696         while (r_framedata_mem->purge)
4697         {
4698                 // repeatedly remove the second item in the list, leaving only head
4699                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4700                 Mem_Free(r_framedata_mem->purge);
4701                 r_framedata_mem->purge = next;
4702         }
4703         // reset the current mem pointer
4704         r_framedata_mem->current = 0;
4705         r_framedata_mem->mark = 0;
4706 }
4707
4708 void *R_FrameData_Alloc(size_t size)
4709 {
4710         void *data;
4711         float newvalue;
4712
4713         // align to 16 byte boundary - the data pointer is already aligned, so we
4714         // only need to ensure the size of every allocation is also aligned
4715         size = (size + 15) & ~15;
4716
4717         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4718         {
4719                 // emergency - we ran out of space, allocate more memory
4720                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4721                 newvalue = r_framedatasize.value * 2.0f;
4722                 // 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
4723                 if (sizeof(size_t) >= 8)
4724                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4725                 else
4726                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4727                 // this might not be a growing it, but we'll allocate another buffer every time
4728                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4729                 R_FrameData_Resize(true);
4730         }
4731
4732         data = r_framedata_mem->data + r_framedata_mem->current;
4733         r_framedata_mem->current += size;
4734
4735         // count the usage for stats
4736         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4737         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4738
4739         return (void *)data;
4740 }
4741
4742 void *R_FrameData_Store(size_t size, void *data)
4743 {
4744         void *d = R_FrameData_Alloc(size);
4745         if (d && data)
4746                 memcpy(d, data, size);
4747         return d;
4748 }
4749
4750 void R_FrameData_SetMark(void)
4751 {
4752         if (!r_framedata_mem)
4753                 return;
4754         r_framedata_mem->mark = r_framedata_mem->current;
4755 }
4756
4757 void R_FrameData_ReturnToMark(void)
4758 {
4759         if (!r_framedata_mem)
4760                 return;
4761         r_framedata_mem->current = r_framedata_mem->mark;
4762 }
4763
4764 //==================================================================================
4765
4766 // avoid reusing the same buffer objects on consecutive frames
4767 #define R_BUFFERDATA_CYCLE 3
4768
4769 typedef struct r_bufferdata_buffer_s
4770 {
4771         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4772         size_t size; // how much usable space
4773         size_t current; // how much space in use
4774         r_meshbuffer_t *buffer; // the buffer itself
4775 }
4776 r_bufferdata_buffer_t;
4777
4778 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4779 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4780
4781 /// frees all dynamic buffers
4782 void R_BufferData_Reset(void)
4783 {
4784         int cycle, type;
4785         r_bufferdata_buffer_t **p, *mem;
4786         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4787         {
4788                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4789                 {
4790                         // free all buffers
4791                         p = &r_bufferdata_buffer[cycle][type];
4792                         while (*p)
4793                         {
4794                                 mem = *p;
4795                                 *p = (*p)->purge;
4796                                 if (mem->buffer)
4797                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4798                                 Mem_Free(mem);
4799                         }
4800                 }
4801         }
4802 }
4803
4804 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4805 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4806 {
4807         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4808         size_t size;
4809         float newvalue = r_buffermegs[type].value;
4810
4811         // increase the cvar if we have to (but only if we already have a mem)
4812         if (mustgrow && mem)
4813                 newvalue *= 2.0f;
4814         newvalue = bound(0.25f, newvalue, 256.0f);
4815         while (newvalue * 1024*1024 < minsize)
4816                 newvalue *= 2.0f;
4817
4818         // clamp the cvar to valid range
4819         newvalue = bound(0.25f, newvalue, 256.0f);
4820         if (r_buffermegs[type].value != newvalue)
4821                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4822
4823         // calculate size in bytes
4824         size = (size_t)(newvalue * 1024*1024);
4825         size = bound(131072, size, 256*1024*1024);
4826
4827         // allocate a new buffer if the size is different (purge old one later)
4828         // or if we were told we must grow the buffer
4829         if (!mem || mem->size != size || mustgrow)
4830         {
4831                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4832                 mem->size = size;
4833                 mem->current = 0;
4834                 if (type == R_BUFFERDATA_VERTEX)
4835                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4836                 else if (type == R_BUFFERDATA_INDEX16)
4837                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4838                 else if (type == R_BUFFERDATA_INDEX32)
4839                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4840                 else if (type == R_BUFFERDATA_UNIFORM)
4841                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4842                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4843                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4844         }
4845 }
4846
4847 void R_BufferData_NewFrame(void)
4848 {
4849         int type;
4850         r_bufferdata_buffer_t **p, *mem;
4851         // cycle to the next frame's buffers
4852         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4853         // if we ran out of space on the last time we used these buffers, free the old memory now
4854         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4855         {
4856                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4857                 {
4858                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4859                         // free all but the head buffer, this is how we recycle obsolete
4860                         // buffers after they are no longer in use
4861                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4862                         while (*p)
4863                         {
4864                                 mem = *p;
4865                                 *p = (*p)->purge;
4866                                 if (mem->buffer)
4867                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4868                                 Mem_Free(mem);
4869                         }
4870                         // reset the current offset
4871                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4872                 }
4873         }
4874 }
4875
4876 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4877 {
4878         r_bufferdata_buffer_t *mem;
4879         int offset = 0;
4880         int padsize;
4881
4882         *returnbufferoffset = 0;
4883
4884         // align size to a byte boundary appropriate for the buffer type, this
4885         // makes all allocations have aligned start offsets
4886         if (type == R_BUFFERDATA_UNIFORM)
4887                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4888         else
4889                 padsize = (datasize + 15) & ~15;
4890
4891         // if we ran out of space in this buffer we must allocate a new one
4892         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)
4893                 R_BufferData_Resize(type, true, padsize);
4894
4895         // if the resize did not give us enough memory, fail
4896         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)
4897                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4898
4899         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4900         offset = (int)mem->current;
4901         mem->current += padsize;
4902
4903         // upload the data to the buffer at the chosen offset
4904         if (offset == 0)
4905                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4906         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4907
4908         // count the usage for stats
4909         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4910         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4911
4912         // return the buffer offset
4913         *returnbufferoffset = offset;
4914
4915         return mem->buffer;
4916 }
4917
4918 //==================================================================================
4919
4920 // LordHavoc: animcache originally written by Echon, rewritten since then
4921
4922 /**
4923  * Animation cache prevents re-generating mesh data for an animated model
4924  * multiple times in one frame for lighting, shadowing, reflections, etc.
4925  */
4926
4927 void R_AnimCache_Free(void)
4928 {
4929 }
4930
4931 void R_AnimCache_ClearCache(void)
4932 {
4933         int i;
4934         entity_render_t *ent;
4935
4936         for (i = 0;i < r_refdef.scene.numentities;i++)
4937         {
4938                 ent = r_refdef.scene.entities[i];
4939                 ent->animcache_vertex3f = NULL;
4940                 ent->animcache_vertex3f_vertexbuffer = NULL;
4941                 ent->animcache_vertex3f_bufferoffset = 0;
4942                 ent->animcache_normal3f = NULL;
4943                 ent->animcache_normal3f_vertexbuffer = NULL;
4944                 ent->animcache_normal3f_bufferoffset = 0;
4945                 ent->animcache_svector3f = NULL;
4946                 ent->animcache_svector3f_vertexbuffer = NULL;
4947                 ent->animcache_svector3f_bufferoffset = 0;
4948                 ent->animcache_tvector3f = NULL;
4949                 ent->animcache_tvector3f_vertexbuffer = NULL;
4950                 ent->animcache_tvector3f_bufferoffset = 0;
4951                 ent->animcache_vertexmesh = NULL;
4952                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4953                 ent->animcache_vertexmesh_bufferoffset = 0;
4954                 ent->animcache_skeletaltransform3x4 = NULL;
4955                 ent->animcache_skeletaltransform3x4buffer = NULL;
4956                 ent->animcache_skeletaltransform3x4offset = 0;
4957                 ent->animcache_skeletaltransform3x4size = 0;
4958         }
4959 }
4960
4961 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4962 {
4963         int i;
4964
4965         // check if we need the meshbuffers
4966         if (!vid.useinterleavedarrays)
4967                 return;
4968
4969         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4970                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4971         // TODO: upload vertexbuffer?
4972         if (ent->animcache_vertexmesh)
4973         {
4974                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4975                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4976                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4977                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4978                 for (i = 0;i < numvertices;i++)
4979                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4980                 if (ent->animcache_svector3f)
4981                         for (i = 0;i < numvertices;i++)
4982                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4983                 if (ent->animcache_tvector3f)
4984                         for (i = 0;i < numvertices;i++)
4985                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4986                 if (ent->animcache_normal3f)
4987                         for (i = 0;i < numvertices;i++)
4988                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4989         }
4990 }
4991
4992 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4993 {
4994         dp_model_t *model = ent->model;
4995         int numvertices;
4996
4997         // see if this ent is worth caching
4998         if (!model || !model->Draw || !model->AnimateVertices)
4999                 return false;
5000         // nothing to cache if it contains no animations and has no skeleton
5001         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5002                 return false;
5003         // see if it is already cached for gpuskeletal
5004         if (ent->animcache_skeletaltransform3x4)
5005                 return false;
5006         // see if it is already cached as a mesh
5007         if (ent->animcache_vertex3f)
5008         {
5009                 // check if we need to add normals or tangents
5010                 if (ent->animcache_normal3f)
5011                         wantnormals = false;
5012                 if (ent->animcache_svector3f)
5013                         wanttangents = false;
5014                 if (!wantnormals && !wanttangents)
5015                         return false;
5016         }
5017
5018         // check which kind of cache we need to generate
5019         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5020         {
5021                 // cache the skeleton so the vertex shader can use it
5022                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5023                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5024                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5025                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5026                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5027                 // note: this can fail if the buffer is at the grow limit
5028                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5029                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5030         }
5031         else if (ent->animcache_vertex3f)
5032         {
5033                 // mesh was already cached but we may need to add normals/tangents
5034                 // (this only happens with multiple views, reflections, cameras, etc)
5035                 if (wantnormals || wanttangents)
5036                 {
5037                         numvertices = model->surfmesh.num_vertices;
5038                         if (wantnormals)
5039                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5040                         if (wanttangents)
5041                         {
5042                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5043                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5044                         }
5045                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5046                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5047                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5048                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5049                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5050                 }
5051         }
5052         else
5053         {
5054                 // generate mesh cache
5055                 numvertices = model->surfmesh.num_vertices;
5056                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5057                 if (wantnormals)
5058                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5059                 if (wanttangents)
5060                 {
5061                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5062                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5063                 }
5064                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5065                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5066                 if (wantnormals || wanttangents)
5067                 {
5068                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5069                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5070                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5071                 }
5072                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5073                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5074                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5075         }
5076         return true;
5077 }
5078
5079 void R_AnimCache_CacheVisibleEntities(void)
5080 {
5081         int i;
5082         qboolean wantnormals = true;
5083         qboolean wanttangents = !r_showsurfaces.integer;
5084
5085         switch(vid.renderpath)
5086         {
5087         case RENDERPATH_GL20:
5088         case RENDERPATH_D3D9:
5089         case RENDERPATH_D3D10:
5090         case RENDERPATH_D3D11:
5091         case RENDERPATH_GLES2:
5092                 break;
5093         case RENDERPATH_GL11:
5094         case RENDERPATH_GL13:
5095         case RENDERPATH_GLES1:
5096                 wanttangents = false;
5097                 break;
5098         case RENDERPATH_SOFT:
5099                 break;
5100         }
5101
5102         if (r_shownormals.integer)
5103                 wanttangents = wantnormals = true;
5104
5105         // TODO: thread this
5106         // NOTE: R_PrepareRTLights() also caches entities
5107
5108         for (i = 0;i < r_refdef.scene.numentities;i++)
5109                 if (r_refdef.viewcache.entityvisible[i])
5110                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5111 }
5112
5113 //==================================================================================
5114
5115 extern cvar_t r_overheadsprites_pushback;
5116
5117 static void R_View_UpdateEntityLighting (void)
5118 {
5119         int i;
5120         entity_render_t *ent;
5121         vec3_t tempdiffusenormal, avg;
5122         vec_t f, fa, fd, fdd;
5123         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5124
5125         for (i = 0;i < r_refdef.scene.numentities;i++)
5126         {
5127                 ent = r_refdef.scene.entities[i];
5128
5129                 // skip unseen models
5130                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5131                         continue;
5132
5133                 // skip bsp models
5134                 if (ent->model && ent->model == cl.worldmodel)
5135                 {
5136                         // TODO: use modellight for r_ambient settings on world?
5137                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5138                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5139                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5140                         continue;
5141                 }
5142                 
5143                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5144                 {
5145                         // aleady updated by CSQC
5146                         // TODO: force modellight on BSP models in this case?
5147                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5148                 }
5149                 else
5150                 {
5151                         // fetch the lighting from the worldmodel data
5152                         VectorClear(ent->modellight_ambient);
5153                         VectorClear(ent->modellight_diffuse);
5154                         VectorClear(tempdiffusenormal);
5155                         if (ent->flags & RENDER_LIGHT)
5156                         {
5157                                 vec3_t org;
5158                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5159
5160                                 // complete lightning for lit sprites
5161                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5162                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5163                                 {
5164                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5165                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5166                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5167                                 }
5168                                 else
5169                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5170
5171                                 if(ent->flags & RENDER_EQUALIZE)
5172                                 {
5173                                         // first fix up ambient lighting...
5174                                         if(r_equalize_entities_minambient.value > 0)
5175                                         {
5176                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5177                                                 if(fd > 0)
5178                                                 {
5179                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5180                                                         if(fa < r_equalize_entities_minambient.value * fd)
5181                                                         {
5182                                                                 // solve:
5183                                                                 //   fa'/fd' = minambient
5184                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5185                                                                 //   ...
5186                                                                 //   fa' = fd' * minambient
5187                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5188                                                                 //   ...
5189                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5190                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5191                                                                 //   ...
5192                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5193                                                                 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5194                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5195                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5196                                                         }
5197                                                 }
5198                                         }
5199
5200                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5201                                         {
5202                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5203                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5204                                                 f = fa + 0.25 * fd;
5205                                                 if(f > 0)
5206                                                 {
5207                                                         // adjust brightness and saturation to target
5208                                                         avg[0] = avg[1] = avg[2] = fa / f;
5209                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5210                                                         avg[0] = avg[1] = avg[2] = fd / f;
5211                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5212                                                 }
5213                                         }
5214                                 }
5215                         }
5216                         else // highly rare
5217                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5218                 }
5219
5220                 // move the light direction into modelspace coordinates for lighting code
5221                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5222                 if(VectorLength2(ent->modellight_lightdir) == 0)
5223                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5224                 VectorNormalize(ent->modellight_lightdir);
5225         }
5226 }
5227
5228 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5229 {
5230         int i;
5231         vec3_t eyemins, eyemaxs;
5232         vec3_t boxmins, boxmaxs;
5233         vec3_t start;
5234         vec3_t end;
5235         dp_model_t *model = r_refdef.scene.worldmodel;
5236         static vec3_t positions[] = {
5237                 { 0.5f, 0.5f, 0.5f },
5238                 { 0.0f, 0.0f, 0.0f },
5239                 { 0.0f, 0.0f, 1.0f },
5240                 { 0.0f, 1.0f, 0.0f },
5241                 { 0.0f, 1.0f, 1.0f },
5242                 { 1.0f, 0.0f, 0.0f },
5243                 { 1.0f, 0.0f, 1.0f },
5244                 { 1.0f, 1.0f, 0.0f },
5245                 { 1.0f, 1.0f, 1.0f },
5246         };
5247
5248         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5249         if (numsamples < 0)
5250                 return true;
5251
5252         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5253         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5254                 return true;
5255
5256         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5257                 return true;
5258
5259         // expand the eye box a little
5260         eyemins[0] = eye[0] - eyejitter;
5261         eyemaxs[0] = eye[0] + eyejitter;
5262         eyemins[1] = eye[1] - eyejitter;
5263         eyemaxs[1] = eye[1] + eyejitter;
5264         eyemins[2] = eye[2] - eyejitter;
5265         eyemaxs[2] = eye[2] + eyejitter;
5266         // expand the box a little
5267         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5268         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5269         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5270         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5271         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5272         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5273
5274         // return true if eye overlaps enlarged box
5275         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5276                 return true;
5277
5278         // try specific positions in the box first - note that these can be cached
5279         if (r_cullentities_trace_entityocclusion.integer)
5280         {
5281                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5282                 {
5283                         VectorCopy(eye, start);
5284                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5285                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5286                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5287                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5288                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5289                         // not picky - if the trace ended anywhere in the box we're good
5290                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5291                                 return true;
5292                 }
5293         }
5294         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5295                 return true;
5296
5297         // try various random positions
5298         for (i = 0; i < numsamples; i++)
5299         {
5300                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5301                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5302                 if (r_cullentities_trace_entityocclusion.integer)
5303                 {
5304                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5305                         // not picky - if the trace ended anywhere in the box we're good
5306                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5307                                 return true;
5308                 }
5309                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5310                         return true;
5311         }
5312
5313         return false;
5314 }
5315
5316
5317 static void R_View_UpdateEntityVisible (void)
5318 {
5319         int i;
5320         int renderimask;
5321         int samples;
5322         entity_render_t *ent;
5323
5324         if (r_refdef.envmap || r_fb.water.hideplayer)
5325                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5326         else if (chase_active.integer || r_fb.water.renderingscene)
5327                 renderimask = RENDER_VIEWMODEL;
5328         else
5329                 renderimask = RENDER_EXTERIORMODEL;
5330         if (!r_drawviewmodel.integer)
5331                 renderimask |= RENDER_VIEWMODEL;
5332         if (!r_drawexteriormodel.integer)
5333                 renderimask |= RENDER_EXTERIORMODEL;
5334         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5335         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5336         {
5337                 // worldmodel can check visibility
5338                 for (i = 0;i < r_refdef.scene.numentities;i++)
5339                 {
5340                         ent = r_refdef.scene.entities[i];
5341                         if (!(ent->flags & renderimask))
5342                         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)))
5343                         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))
5344                                 r_refdef.viewcache.entityvisible[i] = true;
5345                 }
5346         }
5347         else
5348         {
5349                 // no worldmodel or it can't check visibility
5350                 for (i = 0;i < r_refdef.scene.numentities;i++)
5351                 {
5352                         ent = r_refdef.scene.entities[i];
5353                         if (!(ent->flags & renderimask))
5354                         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)))
5355                                 r_refdef.viewcache.entityvisible[i] = true;
5356                 }
5357         }
5358         if (r_cullentities_trace.integer)
5359         {
5360                 for (i = 0;i < r_refdef.scene.numentities;i++)
5361                 {
5362                         if (!r_refdef.viewcache.entityvisible[i])
5363                                 continue;
5364                         ent = r_refdef.scene.entities[i];
5365                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5366                         {
5367                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5368                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5369                                         ent->last_trace_visibility = realtime;
5370                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5371                                         r_refdef.viewcache.entityvisible[i] = 0;
5372                         }
5373                 }
5374         }
5375 }
5376
5377 /// only used if skyrendermasked, and normally returns false
5378 static int R_DrawBrushModelsSky (void)
5379 {
5380         int i, sky;
5381         entity_render_t *ent;
5382
5383         sky = false;
5384         for (i = 0;i < r_refdef.scene.numentities;i++)
5385         {
5386                 if (!r_refdef.viewcache.entityvisible[i])
5387                         continue;
5388                 ent = r_refdef.scene.entities[i];
5389                 if (!ent->model || !ent->model->DrawSky)
5390                         continue;
5391                 ent->model->DrawSky(ent);
5392                 sky = true;
5393         }
5394         return sky;
5395 }
5396
5397 static void R_DrawNoModel(entity_render_t *ent);
5398 static void R_DrawModels(void)
5399 {
5400         int i;
5401         entity_render_t *ent;
5402
5403         for (i = 0;i < r_refdef.scene.numentities;i++)
5404         {
5405                 if (!r_refdef.viewcache.entityvisible[i])
5406                         continue;
5407                 ent = r_refdef.scene.entities[i];
5408                 r_refdef.stats[r_stat_entities]++;
5409                 /*
5410                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5411                 {
5412                         vec3_t f, l, u, o;
5413                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5414                         Con_Printf("R_DrawModels\n");
5415                         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]);
5416                         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);
5417                         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);
5418                 }
5419                 */
5420                 if (ent->model && ent->model->Draw != NULL)
5421                         ent->model->Draw(ent);
5422                 else
5423                         R_DrawNoModel(ent);
5424         }
5425 }
5426
5427 static void R_DrawModelsDepth(void)
5428 {
5429         int i;
5430         entity_render_t *ent;
5431
5432         for (i = 0;i < r_refdef.scene.numentities;i++)
5433         {
5434                 if (!r_refdef.viewcache.entityvisible[i])
5435                         continue;
5436                 ent = r_refdef.scene.entities[i];
5437                 if (ent->model && ent->model->DrawDepth != NULL)
5438                         ent->model->DrawDepth(ent);
5439         }
5440 }
5441
5442 static void R_DrawModelsDebug(void)
5443 {
5444         int i;
5445         entity_render_t *ent;
5446
5447         for (i = 0;i < r_refdef.scene.numentities;i++)
5448         {
5449                 if (!r_refdef.viewcache.entityvisible[i])
5450                         continue;
5451                 ent = r_refdef.scene.entities[i];
5452                 if (ent->model && ent->model->DrawDebug != NULL)
5453                         ent->model->DrawDebug(ent);
5454         }
5455 }
5456
5457 static void R_DrawModelsAddWaterPlanes(void)
5458 {
5459         int i;
5460         entity_render_t *ent;
5461
5462         for (i = 0;i < r_refdef.scene.numentities;i++)
5463         {
5464                 if (!r_refdef.viewcache.entityvisible[i])
5465                         continue;
5466                 ent = r_refdef.scene.entities[i];
5467                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5468                         ent->model->DrawAddWaterPlanes(ent);
5469         }
5470 }
5471
5472 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}};
5473
5474 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5475 {
5476         if (r_hdr_irisadaptation.integer)
5477         {
5478                 vec3_t p;
5479                 vec3_t ambient;
5480                 vec3_t diffuse;
5481                 vec3_t diffusenormal;
5482                 vec3_t forward;
5483                 vec_t brightness = 0.0f;
5484                 vec_t goal;
5485                 vec_t current;
5486                 vec_t d;
5487                 int c;
5488                 VectorCopy(r_refdef.view.forward, forward);
5489                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5490                 {
5491                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5492                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5493                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5494                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5495                         d = DotProduct(forward, diffusenormal);
5496                         brightness += VectorLength(ambient);
5497                         if (d > 0)
5498                                 brightness += d * VectorLength(diffuse);
5499                 }
5500                 brightness *= 1.0f / c;
5501                 brightness += 0.00001f; // make sure it's never zero
5502                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5503                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5504                 current = r_hdr_irisadaptation_value.value;
5505                 if (current < goal)
5506                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5507                 else if (current > goal)
5508                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5509                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5510                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5511         }
5512         else if (r_hdr_irisadaptation_value.value != 1.0f)
5513                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5514 }
5515
5516 static void R_View_SetFrustum(const int *scissor)
5517 {
5518         int i;
5519         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5520         vec3_t forward, left, up, origin, v;
5521
5522         if(scissor)
5523         {
5524                 // flipped x coordinates (because x points left here)
5525                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5526                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5527
5528                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5529                 switch(vid.renderpath)
5530                 {
5531                         case RENDERPATH_D3D9:
5532                         case RENDERPATH_D3D10:
5533                         case RENDERPATH_D3D11:
5534                                 // non-flipped y coordinates
5535                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5536                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5537                                 break;
5538                         case RENDERPATH_SOFT:
5539                         case RENDERPATH_GL11:
5540                         case RENDERPATH_GL13:
5541                         case RENDERPATH_GL20:
5542                         case RENDERPATH_GLES1:
5543                         case RENDERPATH_GLES2:
5544                                 // non-flipped y coordinates
5545                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5546                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5547                                 break;
5548                 }
5549         }
5550
5551         // we can't trust r_refdef.view.forward and friends in reflected scenes
5552         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5553
5554 #if 0
5555         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5556         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5557         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5558         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5559         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5560         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5561         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5562         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5563         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5564         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5565         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5566         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5567 #endif
5568
5569 #if 0
5570         zNear = r_refdef.nearclip;
5571         nudge = 1.0 - 1.0 / (1<<23);
5572         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5573         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5574         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5575         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5576         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5577         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5578         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5579         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5580 #endif
5581
5582
5583
5584 #if 0
5585         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5586         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5587         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5588         r_refdef.view.frustum[0].dist = m[15] - m[12];
5589
5590         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5591         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5592         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5593         r_refdef.view.frustum[1].dist = m[15] + m[12];
5594
5595         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5596         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5597         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5598         r_refdef.view.frustum[2].dist = m[15] - m[13];
5599
5600         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5601         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5602         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5603         r_refdef.view.frustum[3].dist = m[15] + m[13];
5604
5605         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5606         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5607         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5608         r_refdef.view.frustum[4].dist = m[15] - m[14];
5609
5610         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5611         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5612         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5613         r_refdef.view.frustum[5].dist = m[15] + m[14];
5614 #endif
5615
5616         if (r_refdef.view.useperspective)
5617         {
5618                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5619                 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]);
5620                 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]);
5621                 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]);
5622                 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]);
5623
5624                 // then the normals from the corners relative to origin
5625                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5626                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5627                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5628                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5629
5630                 // in a NORMAL view, forward cross left == up
5631                 // in a REFLECTED view, forward cross left == down
5632                 // so our cross products above need to be adjusted for a left handed coordinate system
5633                 CrossProduct(forward, left, v);
5634                 if(DotProduct(v, up) < 0)
5635                 {
5636                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5637                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5638                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5639                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5640                 }
5641
5642                 // Leaving those out was a mistake, those were in the old code, and they
5643                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5644                 // I couldn't reproduce it after adding those normalizations. --blub
5645                 VectorNormalize(r_refdef.view.frustum[0].normal);
5646                 VectorNormalize(r_refdef.view.frustum[1].normal);
5647                 VectorNormalize(r_refdef.view.frustum[2].normal);
5648                 VectorNormalize(r_refdef.view.frustum[3].normal);
5649
5650                 // make the corners absolute
5651                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5652                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5653                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5654                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5655
5656                 // one more normal
5657                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5658
5659                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5660                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5661                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5662                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5663                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5664         }
5665         else
5666         {
5667                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5668                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5669                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5670                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5671                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5672                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5673                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5674                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5675                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5676                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5677         }
5678         r_refdef.view.numfrustumplanes = 5;
5679
5680         if (r_refdef.view.useclipplane)
5681         {
5682                 r_refdef.view.numfrustumplanes = 6;
5683                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5684         }
5685
5686         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5687                 PlaneClassify(r_refdef.view.frustum + i);
5688
5689         // LordHavoc: note to all quake engine coders, Quake had a special case
5690         // for 90 degrees which assumed a square view (wrong), so I removed it,
5691         // Quake2 has it disabled as well.
5692
5693         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5694         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5695         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5696         //PlaneClassify(&frustum[0]);
5697
5698         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5699         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5700         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5701         //PlaneClassify(&frustum[1]);
5702
5703         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5704         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5705         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5706         //PlaneClassify(&frustum[2]);
5707
5708         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5709         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5710         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5711         //PlaneClassify(&frustum[3]);
5712
5713         // nearclip plane
5714         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5715         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5716         //PlaneClassify(&frustum[4]);
5717 }
5718
5719 static void R_View_UpdateWithScissor(const int *myscissor)
5720 {
5721         R_Main_ResizeViewCache();
5722         R_View_SetFrustum(myscissor);
5723         R_View_WorldVisibility(r_refdef.view.useclipplane);
5724         R_View_UpdateEntityVisible();
5725         R_View_UpdateEntityLighting();
5726 }
5727
5728 static void R_View_Update(void)
5729 {
5730         R_Main_ResizeViewCache();
5731         R_View_SetFrustum(NULL);
5732         R_View_WorldVisibility(r_refdef.view.useclipplane);
5733         R_View_UpdateEntityVisible();
5734         R_View_UpdateEntityLighting();
5735 }
5736
5737 float viewscalefpsadjusted = 1.0f;
5738
5739 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5740 {
5741         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5742         scale = bound(0.03125f, scale, 1.0f);
5743         *outwidth = (int)ceil(width * scale);
5744         *outheight = (int)ceil(height * scale);
5745 }
5746
5747 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5748 {
5749         const float *customclipplane = NULL;
5750         float plane[4];
5751         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5752         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5753         {
5754                 // LordHavoc: couldn't figure out how to make this approach the
5755                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5756                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5757                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5758                         dist = r_refdef.view.clipplane.dist;
5759                 plane[0] = r_refdef.view.clipplane.normal[0];
5760                 plane[1] = r_refdef.view.clipplane.normal[1];
5761                 plane[2] = r_refdef.view.clipplane.normal[2];
5762                 plane[3] = -dist;
5763                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5764         }
5765
5766         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5767         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5768
5769         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5770         if (!r_refdef.view.useperspective)
5771                 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);
5772         else if (vid.stencil && r_useinfinitefarclip.integer)
5773                 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);
5774         else
5775                 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);
5776         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5777         R_SetViewport(&r_refdef.view.viewport);
5778         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5779         {
5780                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5781                 float screenplane[4];
5782                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5783                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5784                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5785                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5786                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5787         }
5788 }
5789
5790 void R_EntityMatrix(const matrix4x4_t *matrix)
5791 {
5792         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5793         {
5794                 gl_modelmatrixchanged = false;
5795                 gl_modelmatrix = *matrix;
5796                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5797                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5798                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5799                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5800                 CHECKGLERROR
5801                 switch(vid.renderpath)
5802                 {
5803                 case RENDERPATH_D3D9:
5804 #ifdef SUPPORTD3D
5805                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5806                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5807 #endif
5808                         break;
5809                 case RENDERPATH_D3D10:
5810                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5811                         break;
5812                 case RENDERPATH_D3D11:
5813                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5814                         break;
5815                 case RENDERPATH_GL11:
5816                 case RENDERPATH_GL13:
5817                 case RENDERPATH_GLES1:
5818 #ifndef USE_GLES2
5819                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5820 #endif
5821                         break;
5822                 case RENDERPATH_SOFT:
5823                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5824                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5825                         break;
5826                 case RENDERPATH_GL20:
5827                 case RENDERPATH_GLES2:
5828                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5829                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5830                         break;
5831                 }
5832         }
5833 }
5834
5835 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5836 {
5837         r_viewport_t viewport;
5838
5839         CHECKGLERROR
5840
5841         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5842         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);
5843         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5844         R_SetViewport(&viewport);
5845         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5846         GL_Color(1, 1, 1, 1);
5847         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5848         GL_BlendFunc(GL_ONE, GL_ZERO);
5849         GL_ScissorTest(false);
5850         GL_DepthMask(false);
5851         GL_DepthRange(0, 1);
5852         GL_DepthTest(false);
5853         GL_DepthFunc(GL_LEQUAL);
5854         R_EntityMatrix(&identitymatrix);
5855         R_Mesh_ResetTextureState();
5856         GL_PolygonOffset(0, 0);
5857         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5858         switch(vid.renderpath)
5859         {
5860         case RENDERPATH_GL11:
5861         case RENDERPATH_GL13:
5862         case RENDERPATH_GL20:
5863         case RENDERPATH_GLES1:
5864         case RENDERPATH_GLES2:
5865                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5866                 break;
5867         case RENDERPATH_D3D9:
5868         case RENDERPATH_D3D10:
5869         case RENDERPATH_D3D11:
5870         case RENDERPATH_SOFT:
5871                 break;
5872         }
5873         GL_CullFace(GL_NONE);
5874
5875         CHECKGLERROR
5876 }
5877
5878 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5879 {
5880         DrawQ_Finish();
5881
5882         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5883 }
5884
5885 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5886 {
5887         DrawQ_Finish();
5888
5889         R_SetupView(true, fbo, depthtexture, colortexture);
5890         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5891         GL_Color(1, 1, 1, 1);
5892         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5893         GL_BlendFunc(GL_ONE, GL_ZERO);
5894         GL_ScissorTest(true);
5895         GL_DepthMask(true);
5896         GL_DepthRange(0, 1);
5897         GL_DepthTest(true);
5898         GL_DepthFunc(GL_LEQUAL);
5899         R_EntityMatrix(&identitymatrix);
5900         R_Mesh_ResetTextureState();
5901         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5902         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5903         switch(vid.renderpath)
5904         {
5905         case RENDERPATH_GL11:
5906         case RENDERPATH_GL13:
5907         case RENDERPATH_GL20:
5908         case RENDERPATH_GLES1:
5909         case RENDERPATH_GLES2:
5910                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5911                 break;
5912         case RENDERPATH_D3D9:
5913         case RENDERPATH_D3D10:
5914         case RENDERPATH_D3D11:
5915         case RENDERPATH_SOFT:
5916                 break;
5917         }
5918         GL_CullFace(r_refdef.view.cullface_back);
5919 }
5920
5921 /*
5922 ================
5923 R_RenderView_UpdateViewVectors
5924 ================
5925 */
5926 void R_RenderView_UpdateViewVectors(void)
5927 {
5928         // break apart the view matrix into vectors for various purposes
5929         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5930         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5931         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5932         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5933         // make an inverted copy of the view matrix for tracking sprites
5934         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5935 }
5936
5937 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5938 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5939
5940 static void R_Water_StartFrame(void)
5941 {
5942         int i;
5943         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5944         r_waterstate_waterplane_t *p;
5945         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;
5946
5947         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5948                 return;
5949
5950         switch(vid.renderpath)
5951         {
5952         case RENDERPATH_GL20:
5953         case RENDERPATH_D3D9:
5954         case RENDERPATH_D3D10:
5955         case RENDERPATH_D3D11:
5956         case RENDERPATH_SOFT:
5957         case RENDERPATH_GLES2:
5958                 break;
5959         case RENDERPATH_GL11:
5960         case RENDERPATH_GL13:
5961         case RENDERPATH_GLES1:
5962                 return;
5963         }
5964
5965         // set waterwidth and waterheight to the water resolution that will be
5966         // used (often less than the screen resolution for faster rendering)
5967         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5968
5969         // calculate desired texture sizes
5970         // can't use water if the card does not support the texture size
5971         if (!r_water.integer || r_showsurfaces.integer)
5972                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5973         else if (vid.support.arb_texture_non_power_of_two)
5974         {
5975                 texturewidth = waterwidth;
5976                 textureheight = waterheight;
5977                 camerawidth = waterwidth;
5978                 cameraheight = waterheight;
5979         }
5980         else
5981         {
5982                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5983                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5984                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5985                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5986         }
5987
5988         // allocate textures as needed
5989         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))
5990         {
5991                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5992                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5993                 {
5994                         if (p->texture_refraction)
5995                                 R_FreeTexture(p->texture_refraction);
5996                         p->texture_refraction = NULL;
5997                         if (p->fbo_refraction)
5998                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5999                         p->fbo_refraction = 0;
6000                         if (p->texture_reflection)
6001                                 R_FreeTexture(p->texture_reflection);
6002                         p->texture_reflection = NULL;
6003                         if (p->fbo_reflection)
6004                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6005                         p->fbo_reflection = 0;
6006                         if (p->texture_camera)
6007                                 R_FreeTexture(p->texture_camera);
6008                         p->texture_camera = NULL;
6009                         if (p->fbo_camera)
6010                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6011                         p->fbo_camera = 0;
6012                 }
6013                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6014                 r_fb.water.texturewidth = texturewidth;
6015                 r_fb.water.textureheight = textureheight;
6016                 r_fb.water.camerawidth = camerawidth;
6017                 r_fb.water.cameraheight = cameraheight;
6018         }
6019
6020         if (r_fb.water.texturewidth)
6021         {
6022                 int scaledwidth, scaledheight;
6023
6024                 r_fb.water.enabled = true;
6025
6026                 // water resolution is usually reduced
6027                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6028                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6029                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6030
6031                 // set up variables that will be used in shader setup
6032                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6033                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6034                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6035                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6036         }
6037
6038         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6039         r_fb.water.numwaterplanes = 0;
6040 }
6041
6042 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6043 {
6044         int planeindex, bestplaneindex, vertexindex;
6045         vec3_t mins, maxs, normal, center, v, n;
6046         vec_t planescore, bestplanescore;
6047         mplane_t plane;
6048         r_waterstate_waterplane_t *p;
6049         texture_t *t = R_GetCurrentTexture(surface->texture);
6050
6051         rsurface.texture = t;
6052         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6053         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6054         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6055                 return;
6056         // average the vertex normals, find the surface bounds (after deformvertexes)
6057         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6058         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6059         VectorCopy(n, normal);
6060         VectorCopy(v, mins);
6061         VectorCopy(v, maxs);
6062         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6063         {
6064                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6065                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6066                 VectorAdd(normal, n, normal);
6067                 mins[0] = min(mins[0], v[0]);
6068                 mins[1] = min(mins[1], v[1]);
6069                 mins[2] = min(mins[2], v[2]);
6070                 maxs[0] = max(maxs[0], v[0]);
6071                 maxs[1] = max(maxs[1], v[1]);
6072                 maxs[2] = max(maxs[2], v[2]);
6073         }
6074         VectorNormalize(normal);
6075         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6076
6077         VectorCopy(normal, plane.normal);
6078         VectorNormalize(plane.normal);
6079         plane.dist = DotProduct(center, plane.normal);
6080         PlaneClassify(&plane);
6081         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6082         {
6083                 // skip backfaces (except if nocullface is set)
6084 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6085 //                      return;
6086                 VectorNegate(plane.normal, plane.normal);
6087                 plane.dist *= -1;
6088                 PlaneClassify(&plane);
6089         }
6090
6091
6092         // find a matching plane if there is one
6093         bestplaneindex = -1;
6094         bestplanescore = 1048576.0f;
6095         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6096         {
6097                 if(p->camera_entity == t->camera_entity)
6098                 {
6099                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6100                         if (bestplaneindex < 0 || bestplanescore > planescore)
6101                         {
6102                                 bestplaneindex = planeindex;
6103                                 bestplanescore = planescore;
6104                         }
6105                 }
6106         }
6107         planeindex = bestplaneindex;
6108
6109         // if this surface does not fit any known plane rendered this frame, add one
6110         if (planeindex < 0 || bestplanescore > 0.001f)
6111         {
6112                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6113                 {
6114                         // store the new plane
6115                         planeindex = r_fb.water.numwaterplanes++;
6116                         p = r_fb.water.waterplanes + planeindex;
6117                         p->plane = plane;
6118                         // clear materialflags and pvs
6119                         p->materialflags = 0;
6120                         p->pvsvalid = false;
6121                         p->camera_entity = t->camera_entity;
6122                         VectorCopy(mins, p->mins);
6123                         VectorCopy(maxs, p->maxs);
6124                 }
6125                 else
6126                 {
6127                         // We're totally screwed.
6128                         return;
6129                 }
6130         }
6131         else
6132         {
6133                 // merge mins/maxs when we're adding this surface to the plane
6134                 p = r_fb.water.waterplanes + planeindex;
6135                 p->mins[0] = min(p->mins[0], mins[0]);
6136                 p->mins[1] = min(p->mins[1], mins[1]);
6137                 p->mins[2] = min(p->mins[2], mins[2]);
6138                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6139                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6140                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6141         }
6142         // merge this surface's materialflags into the waterplane
6143         p->materialflags |= t->currentmaterialflags;
6144         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6145         {
6146                 // merge this surface's PVS into the waterplane
6147                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6148                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6149                 {
6150                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6151                         p->pvsvalid = true;
6152                 }
6153         }
6154 }
6155
6156 extern cvar_t r_drawparticles;
6157 extern cvar_t r_drawdecals;
6158
6159 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6160 {
6161         int myscissor[4];
6162         r_refdef_view_t originalview;
6163         r_refdef_view_t myview;
6164         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;
6165         r_waterstate_waterplane_t *p;
6166         vec3_t visorigin;
6167         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;
6168         char vabuf[1024];
6169
6170         originalview = r_refdef.view;
6171
6172         // lowquality hack, temporarily shut down some cvars and restore afterwards
6173         qualityreduction = r_water_lowquality.integer;
6174         if (qualityreduction > 0)
6175         {
6176                 if (qualityreduction >= 1)
6177                 {
6178                         old_r_shadows = r_shadows.integer;
6179                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6180                         old_r_dlight = r_shadow_realtime_dlight.integer;
6181                         Cvar_SetValueQuick(&r_shadows, 0);
6182                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6183                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6184                 }
6185                 if (qualityreduction >= 2)
6186                 {
6187                         old_r_dynamic = r_dynamic.integer;
6188                         old_r_particles = r_drawparticles.integer;
6189                         old_r_decals = r_drawdecals.integer;
6190                         Cvar_SetValueQuick(&r_dynamic, 0);
6191                         Cvar_SetValueQuick(&r_drawparticles, 0);
6192                         Cvar_SetValueQuick(&r_drawdecals, 0);
6193                 }
6194         }
6195
6196         // make sure enough textures are allocated
6197         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6198         {
6199                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6200                         continue;
6201                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6202                 {
6203                         if (!p->texture_refraction)
6204                                 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);
6205                         if (!p->texture_refraction)
6206                                 goto error;
6207                         if (usewaterfbo)
6208                         {
6209                                 if (r_fb.water.depthtexture == NULL)
6210                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6211                                 if (p->fbo_refraction == 0)
6212                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6213                         }
6214                 }
6215                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6216                 {
6217                         if (!p->texture_camera)
6218                                 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);
6219                         if (!p->texture_camera)
6220                                 goto error;
6221                         if (usewaterfbo)
6222                         {
6223                                 if (r_fb.water.depthtexture == NULL)
6224                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6225                                 if (p->fbo_camera == 0)
6226                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6227                         }
6228                 }
6229
6230                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6231                 {
6232                         if (!p->texture_reflection)
6233                                 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);
6234                         if (!p->texture_reflection)
6235                                 goto error;
6236                         if (usewaterfbo)
6237                         {
6238                                 if (r_fb.water.depthtexture == NULL)
6239                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6240                                 if (p->fbo_reflection == 0)
6241                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6242                         }
6243                 }
6244         }
6245
6246         // render views
6247         r_refdef.view = originalview;
6248         r_refdef.view.showdebug = false;
6249         r_refdef.view.width = r_fb.water.waterwidth;
6250         r_refdef.view.height = r_fb.water.waterheight;
6251         r_refdef.view.useclipplane = true;
6252         myview = r_refdef.view;
6253         r_fb.water.renderingscene = true;
6254         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6255         {
6256                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6257                         continue;
6258                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6259                 {
6260                         r_refdef.view = myview;
6261                         if(r_water_scissormode.integer)
6262                         {
6263                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6264                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6265                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6266                         }
6267
6268                         // render reflected scene and copy into texture
6269                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6270                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6271                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6272                         r_refdef.view.clipplane = p->plane;
6273                         // reverse the cullface settings for this render
6274                         r_refdef.view.cullface_front = GL_FRONT;
6275                         r_refdef.view.cullface_back = GL_BACK;
6276                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6277                         {
6278                                 r_refdef.view.usecustompvs = true;
6279                                 if (p->pvsvalid)
6280                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6281                                 else
6282                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6283                         }
6284
6285                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6286                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6287                         R_ClearScreen(r_refdef.fogenabled);
6288                         if(r_water_scissormode.integer & 2)
6289                                 R_View_UpdateWithScissor(myscissor);
6290                         else
6291                                 R_View_Update();
6292                         R_AnimCache_CacheVisibleEntities();
6293                         if(r_water_scissormode.integer & 1)
6294                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6295                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6296
6297                         if (!p->fbo_reflection)
6298                                 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);
6299                         r_fb.water.hideplayer = false;
6300                 }
6301
6302                 // render the normal view scene and copy into texture
6303                 // (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)
6304                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6305                 {
6306                         r_refdef.view = myview;
6307                         if(r_water_scissormode.integer)
6308                         {
6309                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6310                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6311                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6312                         }
6313
6314                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6315
6316                         r_refdef.view.clipplane = p->plane;
6317                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6318                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6319
6320                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6321                         {
6322                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6323                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6324                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6325                                 R_RenderView_UpdateViewVectors();
6326                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6327                                 {
6328                                         r_refdef.view.usecustompvs = true;
6329                                         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);
6330                                 }
6331                         }
6332
6333                         PlaneClassify(&r_refdef.view.clipplane);
6334
6335                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6336                         R_ClearScreen(r_refdef.fogenabled);
6337                         if(r_water_scissormode.integer & 2)
6338                                 R_View_UpdateWithScissor(myscissor);
6339                         else
6340                                 R_View_Update();
6341                         R_AnimCache_CacheVisibleEntities();
6342                         if(r_water_scissormode.integer & 1)
6343                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6344                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6345
6346                         if (!p->fbo_refraction)
6347                                 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);
6348                         r_fb.water.hideplayer = false;
6349                 }
6350                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6351                 {
6352                         r_refdef.view = myview;
6353
6354                         r_refdef.view.clipplane = p->plane;
6355                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6356                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6357
6358                         r_refdef.view.width = r_fb.water.camerawidth;
6359                         r_refdef.view.height = r_fb.water.cameraheight;
6360                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6361                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6362                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6363                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6364
6365                         if(p->camera_entity)
6366                         {
6367                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6368                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6369                         }
6370
6371                         // note: all of the view is used for displaying... so
6372                         // there is no use in scissoring
6373
6374                         // reverse the cullface settings for this render
6375                         r_refdef.view.cullface_front = GL_FRONT;
6376                         r_refdef.view.cullface_back = GL_BACK;
6377                         // also reverse the view matrix
6378                         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
6379                         R_RenderView_UpdateViewVectors();
6380                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6381                         {
6382                                 r_refdef.view.usecustompvs = true;
6383                                 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);
6384                         }
6385                         
6386                         // camera needs no clipplane
6387                         r_refdef.view.useclipplane = false;
6388
6389                         PlaneClassify(&r_refdef.view.clipplane);
6390
6391                         r_fb.water.hideplayer = false;
6392
6393                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6394                         R_ClearScreen(r_refdef.fogenabled);
6395                         R_View_Update();
6396                         R_AnimCache_CacheVisibleEntities();
6397                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6398
6399                         if (!p->fbo_camera)
6400                                 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);
6401                         r_fb.water.hideplayer = false;
6402                 }
6403
6404         }
6405         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6406         r_fb.water.renderingscene = false;
6407         r_refdef.view = originalview;
6408         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6409         if (!r_fb.water.depthtexture)
6410                 R_ClearScreen(r_refdef.fogenabled);
6411         R_View_Update();
6412         R_AnimCache_CacheVisibleEntities();
6413         goto finish;
6414 error:
6415         r_refdef.view = originalview;
6416         r_fb.water.renderingscene = false;
6417         Cvar_SetValueQuick(&r_water, 0);
6418         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6419 finish:
6420         // lowquality hack, restore cvars
6421         if (qualityreduction > 0)
6422         {
6423                 if (qualityreduction >= 1)
6424                 {
6425                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6426                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6427                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6428                 }
6429                 if (qualityreduction >= 2)
6430                 {
6431                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6432                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6433                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6434                 }
6435         }
6436 }
6437
6438 static void R_Bloom_StartFrame(void)
6439 {
6440         int i;
6441         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6442         int viewwidth, viewheight;
6443         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6444         textype_t textype = TEXTYPE_COLORBUFFER;
6445
6446         switch (vid.renderpath)
6447         {
6448         case RENDERPATH_GL20:
6449                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6450                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6451                 {
6452                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6453                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6454                 }
6455                 break;
6456         case RENDERPATH_GL11:
6457         case RENDERPATH_GL13:
6458         case RENDERPATH_GLES1:
6459         case RENDERPATH_GLES2:
6460         case RENDERPATH_D3D9:
6461         case RENDERPATH_D3D10:
6462         case RENDERPATH_D3D11:
6463                 r_fb.usedepthtextures = false;
6464                 break;
6465         case RENDERPATH_SOFT:
6466                 r_fb.usedepthtextures = true;
6467                 break;
6468         }
6469
6470         if (r_viewscale_fpsscaling.integer)
6471         {
6472                 double actualframetime;
6473                 double targetframetime;
6474                 double adjust;
6475                 actualframetime = r_refdef.lastdrawscreentime;
6476                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6477                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6478                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6479                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6480                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6481                 viewscalefpsadjusted += adjust;
6482                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6483         }
6484         else
6485                 viewscalefpsadjusted = 1.0f;
6486
6487         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6488
6489         switch(vid.renderpath)
6490         {
6491         case RENDERPATH_GL20:
6492         case RENDERPATH_D3D9:
6493         case RENDERPATH_D3D10:
6494         case RENDERPATH_D3D11:
6495         case RENDERPATH_SOFT:
6496         case RENDERPATH_GLES2:
6497                 break;
6498         case RENDERPATH_GL11:
6499         case RENDERPATH_GL13:
6500         case RENDERPATH_GLES1:
6501                 return;
6502         }
6503
6504         // set bloomwidth and bloomheight to the bloom resolution that will be
6505         // used (often less than the screen resolution for faster rendering)
6506         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6507         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6508         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6509         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6510         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6511
6512         // calculate desired texture sizes
6513         if (vid.support.arb_texture_non_power_of_two)
6514         {
6515                 screentexturewidth = vid.width;
6516                 screentextureheight = vid.height;
6517                 bloomtexturewidth = r_fb.bloomwidth;
6518                 bloomtextureheight = r_fb.bloomheight;
6519         }
6520         else
6521         {
6522                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6523                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6524                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6525                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6526         }
6527
6528         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))
6529         {
6530                 Cvar_SetValueQuick(&r_bloom, 0);
6531                 Cvar_SetValueQuick(&r_motionblur, 0);
6532                 Cvar_SetValueQuick(&r_damageblur, 0);
6533         }
6534
6535         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6536          && !r_bloom.integer
6537          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6538          && !useviewfbo
6539          && r_viewscale.value == 1.0f
6540          && !r_viewscale_fpsscaling.integer)
6541                 screentexturewidth = screentextureheight = 0;
6542         if (!r_bloom.integer)
6543                 bloomtexturewidth = bloomtextureheight = 0;
6544
6545         // allocate textures as needed
6546         if (r_fb.screentexturewidth != screentexturewidth
6547          || r_fb.screentextureheight != screentextureheight
6548          || r_fb.bloomtexturewidth != bloomtexturewidth
6549          || r_fb.bloomtextureheight != bloomtextureheight
6550          || r_fb.textype != textype
6551          || useviewfbo != (r_fb.fbo != 0))
6552         {
6553                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6554                 {
6555                         if (r_fb.bloomtexture[i])
6556                                 R_FreeTexture(r_fb.bloomtexture[i]);
6557                         r_fb.bloomtexture[i] = NULL;
6558
6559                         if (r_fb.bloomfbo[i])
6560                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6561                         r_fb.bloomfbo[i] = 0;
6562                 }
6563
6564                 if (r_fb.fbo)
6565                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6566                 r_fb.fbo = 0;
6567
6568                 if (r_fb.colortexture)
6569                         R_FreeTexture(r_fb.colortexture);
6570                 r_fb.colortexture = NULL;
6571
6572                 if (r_fb.depthtexture)
6573                         R_FreeTexture(r_fb.depthtexture);
6574                 r_fb.depthtexture = NULL;
6575
6576                 if (r_fb.ghosttexture)
6577                         R_FreeTexture(r_fb.ghosttexture);
6578                 r_fb.ghosttexture = NULL;
6579
6580                 r_fb.screentexturewidth = screentexturewidth;
6581                 r_fb.screentextureheight = screentextureheight;
6582                 r_fb.bloomtexturewidth = bloomtexturewidth;
6583                 r_fb.bloomtextureheight = bloomtextureheight;
6584                 r_fb.textype = textype;
6585
6586                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6587                 {
6588                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6589                                 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);
6590                         r_fb.ghosttexture_valid = false;
6591                         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);
6592                         if (useviewfbo)
6593                         {
6594                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6595                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6596                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6597                         }
6598                 }
6599
6600                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6601                 {
6602                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6603                         {
6604                                 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);
6605                                 if (useviewfbo)
6606                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6607                         }
6608                 }
6609         }
6610
6611         // bloom texture is a different resolution
6612         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6613         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6614         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6615         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6616         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6617
6618         // set up a texcoord array for the full resolution screen image
6619         // (we have to keep this around to copy back during final render)
6620         r_fb.screentexcoord2f[0] = 0;
6621         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6622         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6623         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6624         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6625         r_fb.screentexcoord2f[5] = 0;
6626         r_fb.screentexcoord2f[6] = 0;
6627         r_fb.screentexcoord2f[7] = 0;
6628
6629         if(r_fb.fbo) 
6630         {
6631                 for (i = 1;i < 8;i += 2)
6632                 {
6633                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6634                 }
6635         }
6636
6637         // set up a texcoord array for the reduced resolution bloom image
6638         // (which will be additive blended over the screen image)
6639         r_fb.bloomtexcoord2f[0] = 0;
6640         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6641         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6642         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6643         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6644         r_fb.bloomtexcoord2f[5] = 0;
6645         r_fb.bloomtexcoord2f[6] = 0;
6646         r_fb.bloomtexcoord2f[7] = 0;
6647
6648         switch(vid.renderpath)
6649         {
6650         case RENDERPATH_GL11:
6651         case RENDERPATH_GL13:
6652         case RENDERPATH_GL20:
6653         case RENDERPATH_SOFT:
6654         case RENDERPATH_GLES1:
6655         case RENDERPATH_GLES2:
6656                 break;
6657         case RENDERPATH_D3D9:
6658         case RENDERPATH_D3D10:
6659         case RENDERPATH_D3D11:
6660                 for (i = 0;i < 4;i++)
6661                 {
6662                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6663                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6664                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6665                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6666                 }
6667                 break;
6668         }
6669
6670         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6671
6672         if (r_fb.fbo)
6673                 r_refdef.view.clear = true;
6674 }
6675
6676 static void R_Bloom_MakeTexture(void)
6677 {
6678         int x, range, dir;
6679         float xoffset, yoffset, r, brighten;
6680         rtexture_t *intex;
6681         float colorscale = r_bloom_colorscale.value;
6682
6683         r_refdef.stats[r_stat_bloom]++;
6684     
6685 #if 0
6686     // this copy is unnecessary since it happens in R_BlendView already
6687         if (!r_fb.fbo)
6688         {
6689                 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);
6690                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6691         }
6692 #endif
6693
6694         // scale down screen texture to the bloom texture size
6695         CHECKGLERROR
6696         r_fb.bloomindex = 0;
6697         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6698         R_SetViewport(&r_fb.bloomviewport);
6699         GL_CullFace(GL_NONE);
6700         GL_DepthTest(false);
6701         GL_BlendFunc(GL_ONE, GL_ZERO);
6702         GL_Color(colorscale, colorscale, colorscale, 1);
6703         // 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...
6704         switch(vid.renderpath)
6705         {
6706         case RENDERPATH_GL11:
6707         case RENDERPATH_GL13:
6708         case RENDERPATH_GL20:
6709         case RENDERPATH_GLES1:
6710         case RENDERPATH_GLES2:
6711         case RENDERPATH_SOFT:
6712                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6713                 break;
6714         case RENDERPATH_D3D9:
6715         case RENDERPATH_D3D10:
6716         case RENDERPATH_D3D11:
6717                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6718                 break;
6719         }
6720         // TODO: do boxfilter scale-down in shader?
6721         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6722         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6723         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6724
6725         // we now have a properly scaled bloom image
6726         if (!r_fb.bloomfbo[r_fb.bloomindex])
6727         {
6728                 // copy it into the bloom texture
6729                 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);
6730                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6731         }
6732
6733         // multiply bloom image by itself as many times as desired
6734         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6735         {
6736                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6737                 r_fb.bloomindex ^= 1;
6738                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6739                 x *= 2;
6740                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6741                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6742                 {
6743                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6744                         GL_Color(r,r,r,1); // apply fix factor
6745                 }
6746                 else
6747                 {
6748                         if(x <= 2)
6749                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6750                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6751                         GL_Color(1,1,1,1); // no fix factor supported here
6752                 }
6753                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6754                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6755                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6756                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6757
6758                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6759                 {
6760                         // copy the darkened image to a texture
6761                         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);
6762                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6763                 }
6764         }
6765
6766         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6767         brighten = r_bloom_brighten.value;
6768         brighten = sqrt(brighten);
6769         if(range >= 1)
6770                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6771
6772         for (dir = 0;dir < 2;dir++)
6773         {
6774                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6775                 r_fb.bloomindex ^= 1;
6776                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6777                 // blend on at multiple vertical offsets to achieve a vertical blur
6778                 // TODO: do offset blends using GLSL
6779                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6780                 GL_BlendFunc(GL_ONE, GL_ZERO);
6781                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6782                 for (x = -range;x <= range;x++)
6783                 {
6784                         if (!dir){xoffset = 0;yoffset = x;}
6785                         else {xoffset = x;yoffset = 0;}
6786                         xoffset /= (float)r_fb.bloomtexturewidth;
6787                         yoffset /= (float)r_fb.bloomtextureheight;
6788                         // compute a texcoord array with the specified x and y offset
6789                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6790                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6791                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6792                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6793                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6794                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6795                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6796                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6797                         // this r value looks like a 'dot' particle, fading sharply to
6798                         // black at the edges
6799                         // (probably not realistic but looks good enough)
6800                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6801                         //r = brighten/(range*2+1);
6802                         r = brighten / (range * 2 + 1);
6803                         if(range >= 1)
6804                                 r *= (1 - x*x/(float)(range*range));
6805                         GL_Color(r, r, r, 1);
6806                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6807                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6808                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6809                         GL_BlendFunc(GL_ONE, GL_ONE);
6810                 }
6811
6812                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6813                 {
6814                         // copy the vertically or horizontally blurred bloom view to a texture
6815                         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);
6816                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6817                 }
6818         }
6819 }
6820
6821 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6822 {
6823         dpuint64 permutation;
6824         float uservecs[4][4];
6825
6826         R_EntityMatrix(&identitymatrix);
6827
6828         switch (vid.renderpath)
6829         {
6830         case RENDERPATH_GL20:
6831         case RENDERPATH_D3D9:
6832         case RENDERPATH_D3D10:
6833         case RENDERPATH_D3D11:
6834         case RENDERPATH_SOFT:
6835         case RENDERPATH_GLES2:
6836                 permutation =
6837                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6838                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6839                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6840                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6841                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6842
6843                 if (r_fb.colortexture)
6844                 {
6845                         if (!r_fb.fbo)
6846                         {
6847                                 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);
6848                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6849                         }
6850
6851                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6852                         {
6853                                 // declare variables
6854                                 float blur_factor, blur_mouseaccel, blur_velocity;
6855                                 static float blur_average; 
6856                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6857
6858                                 // set a goal for the factoring
6859                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6860                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6861                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6862                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6863                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6864                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6865
6866                                 // from the goal, pick an averaged value between goal and last value
6867                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6868                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6869
6870                                 // enforce minimum amount of blur 
6871                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6872
6873                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6874
6875                                 // calculate values into a standard alpha
6876                                 cl.motionbluralpha = 1 - exp(-
6877                                                 (
6878                                                  (r_motionblur.value * blur_factor / 80)
6879                                                  +
6880                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6881                                                 )
6882                                                 /
6883                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6884                                           );
6885
6886                                 // randomization for the blur value to combat persistent ghosting
6887                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6888                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6889
6890                                 // apply the blur
6891                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6892                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6893                                 {
6894                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6895                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6896                                         switch(vid.renderpath)
6897                                         {
6898                                         case RENDERPATH_GL11:
6899                                         case RENDERPATH_GL13:
6900                                         case RENDERPATH_GL20:
6901                                         case RENDERPATH_GLES1:
6902                                         case RENDERPATH_GLES2:
6903                                         case RENDERPATH_SOFT:
6904                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6905                                                 break;
6906                                         case RENDERPATH_D3D9:
6907                                         case RENDERPATH_D3D10:
6908                                         case RENDERPATH_D3D11:
6909                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6910                                                 break;
6911                                         }
6912                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6913                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6914                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6915                                 }
6916
6917                                 // updates old view angles for next pass
6918                                 VectorCopy(cl.viewangles, blur_oldangles);
6919
6920                                 // copy view into the ghost texture
6921                                 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);
6922                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6923                                 r_fb.ghosttexture_valid = true;
6924                         }
6925                 }
6926                 else
6927                 {
6928                         // no r_fb.colortexture means we're rendering to the real fb
6929                         // we may still have to do view tint...
6930                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6931                         {
6932                                 // apply a color tint to the whole view
6933                                 R_ResetViewRendering2D(0, NULL, NULL);
6934                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6935                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6936                                 R_SetupShader_Generic_NoTexture(false, true);
6937                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6938                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6939                         }
6940                         break; // no screen processing, no bloom, skip it
6941                 }
6942
6943                 if (r_fb.bloomtexture[0])
6944                 {
6945                         // make the bloom texture
6946                         R_Bloom_MakeTexture();
6947                 }
6948
6949 #if _MSC_VER >= 1400
6950 #define sscanf sscanf_s
6951 #endif
6952                 memset(uservecs, 0, sizeof(uservecs));
6953                 if (r_glsl_postprocess_uservec1_enable.integer)
6954                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6955                 if (r_glsl_postprocess_uservec2_enable.integer)
6956                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6957                 if (r_glsl_postprocess_uservec3_enable.integer)
6958                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6959                 if (r_glsl_postprocess_uservec4_enable.integer)
6960                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6961
6962                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6963                 GL_Color(1, 1, 1, 1);
6964                 GL_BlendFunc(GL_ONE, GL_ZERO);
6965
6966                 switch(vid.renderpath)
6967                 {
6968                 case RENDERPATH_GL20:
6969                 case RENDERPATH_GLES2:
6970                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6971                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6972                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6973                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6974                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6975                         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]);
6976                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6977                         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]);
6978                         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]);
6979                         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]);
6980                         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]);
6981                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6982                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6983                         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);
6984                         break;
6985                 case RENDERPATH_D3D9:
6986 #ifdef SUPPORTD3D
6987                         // 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...
6988                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6989                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6990                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6991                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6992                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6993                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6994                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6995                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6996                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6997                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6998                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6999                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
7000                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7001                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7002 #endif
7003                         break;
7004                 case RENDERPATH_D3D10:
7005                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7006                         break;
7007                 case RENDERPATH_D3D11:
7008                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7009                         break;
7010                 case RENDERPATH_SOFT:
7011                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7012                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7013                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7014                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7015                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7016                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7017                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7018                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7019                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7020                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7021                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7022                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7023                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7024                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7025                         break;
7026                 default:
7027                         break;
7028                 }
7029                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7030                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7031                 break;
7032         case RENDERPATH_GL11:
7033         case RENDERPATH_GL13:
7034         case RENDERPATH_GLES1:
7035                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7036                 {
7037                         // apply a color tint to the whole view
7038                         R_ResetViewRendering2D(0, NULL, NULL);
7039                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7040                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7041                         R_SetupShader_Generic_NoTexture(false, true);
7042                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7043                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7044                 }
7045                 break;
7046         }
7047 }
7048
7049 matrix4x4_t r_waterscrollmatrix;
7050
7051 void R_UpdateFog(void)
7052 {
7053         // Nehahra fog
7054         if (gamemode == GAME_NEHAHRA)
7055         {
7056                 if (gl_fogenable.integer)
7057                 {
7058                         r_refdef.oldgl_fogenable = true;
7059                         r_refdef.fog_density = gl_fogdensity.value;
7060                         r_refdef.fog_red = gl_fogred.value;
7061                         r_refdef.fog_green = gl_foggreen.value;
7062                         r_refdef.fog_blue = gl_fogblue.value;
7063                         r_refdef.fog_alpha = 1;
7064                         r_refdef.fog_start = 0;
7065                         r_refdef.fog_end = gl_skyclip.value;
7066                         r_refdef.fog_height = 1<<30;
7067                         r_refdef.fog_fadedepth = 128;
7068                 }
7069                 else if (r_refdef.oldgl_fogenable)
7070                 {
7071                         r_refdef.oldgl_fogenable = false;
7072                         r_refdef.fog_density = 0;
7073                         r_refdef.fog_red = 0;
7074                         r_refdef.fog_green = 0;
7075                         r_refdef.fog_blue = 0;
7076                         r_refdef.fog_alpha = 0;
7077                         r_refdef.fog_start = 0;
7078                         r_refdef.fog_end = 0;
7079                         r_refdef.fog_height = 1<<30;
7080                         r_refdef.fog_fadedepth = 128;
7081                 }
7082         }
7083
7084         // fog parms
7085         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7086         r_refdef.fog_start = max(0, r_refdef.fog_start);
7087         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7088
7089         if (r_refdef.fog_density && r_drawfog.integer)
7090         {
7091                 r_refdef.fogenabled = true;
7092                 // this is the point where the fog reaches 0.9986 alpha, which we
7093                 // consider a good enough cutoff point for the texture
7094                 // (0.9986 * 256 == 255.6)
7095                 if (r_fog_exp2.integer)
7096                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7097                 else
7098                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7099                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7100                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7101                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7102                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7103                         R_BuildFogHeightTexture();
7104                 // fog color was already set
7105                 // update the fog texture
7106                 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)
7107                         R_BuildFogTexture();
7108                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7109                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7110         }
7111         else
7112                 r_refdef.fogenabled = false;
7113
7114         // fog color
7115         if (r_refdef.fog_density)
7116         {
7117                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7118                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7119                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7120
7121                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7122                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7123                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7124                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7125
7126                 {
7127                         vec3_t fogvec;
7128                         VectorCopy(r_refdef.fogcolor, fogvec);
7129                         //   color.rgb *= ContrastBoost * SceneBrightness;
7130                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7131                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7132                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7133                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7134                 }
7135         }
7136 }
7137
7138 void R_UpdateVariables(void)
7139 {
7140         R_Textures_Frame();
7141
7142         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7143
7144         r_refdef.farclip = r_farclip_base.value;
7145         if (r_refdef.scene.worldmodel)
7146                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7147         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7148
7149         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7150                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7151         r_refdef.polygonfactor = 0;
7152         r_refdef.polygonoffset = 0;
7153         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7154         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7155
7156         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7157         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7158         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7159         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7160         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7161         if (FAKELIGHT_ENABLED)
7162         {
7163                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7164         }
7165         else if (r_refdef.scene.worldmodel)
7166         {
7167                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7168         }
7169         if (r_showsurfaces.integer)
7170         {
7171                 r_refdef.scene.rtworld = false;
7172                 r_refdef.scene.rtworldshadows = false;
7173                 r_refdef.scene.rtdlight = false;
7174                 r_refdef.scene.rtdlightshadows = false;
7175                 r_refdef.lightmapintensity = 0;
7176         }
7177
7178         r_gpuskeletal = false;
7179         switch(vid.renderpath)
7180         {
7181         case RENDERPATH_GL20:
7182                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7183         case RENDERPATH_D3D9:
7184         case RENDERPATH_D3D10:
7185         case RENDERPATH_D3D11:
7186         case RENDERPATH_SOFT:
7187         case RENDERPATH_GLES2:
7188                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7189                 {
7190                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7191                         {
7192                                 // build GLSL gamma texture
7193 #define RAMPWIDTH 256
7194                                 unsigned short ramp[RAMPWIDTH * 3];
7195                                 unsigned char rampbgr[RAMPWIDTH][4];
7196                                 int i;
7197
7198                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7199
7200                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7201                                 for(i = 0; i < RAMPWIDTH; ++i)
7202                                 {
7203                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7204                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7205                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7206                                         rampbgr[i][3] = 0;
7207                                 }
7208                                 if (r_texture_gammaramps)
7209                                 {
7210                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7211                                 }
7212                                 else
7213                                 {
7214                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7215                                 }
7216                         }
7217                 }
7218                 else
7219                 {
7220                         // remove GLSL gamma texture
7221                 }
7222                 break;
7223         case RENDERPATH_GL11:
7224         case RENDERPATH_GL13:
7225         case RENDERPATH_GLES1:
7226                 break;
7227         }
7228 }
7229
7230 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7231 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7232 /*
7233 ================
7234 R_SelectScene
7235 ================
7236 */
7237 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7238         if( scenetype != r_currentscenetype ) {
7239                 // store the old scenetype
7240                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7241                 r_currentscenetype = scenetype;
7242                 // move in the new scene
7243                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7244         }
7245 }
7246
7247 /*
7248 ================
7249 R_GetScenePointer
7250 ================
7251 */
7252 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7253 {
7254         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7255         if( scenetype == r_currentscenetype ) {
7256                 return &r_refdef.scene;
7257         } else {
7258                 return &r_scenes_store[ scenetype ];
7259         }
7260 }
7261
7262 static int R_SortEntities_Compare(const void *ap, const void *bp)
7263 {
7264         const entity_render_t *a = *(const entity_render_t **)ap;
7265         const entity_render_t *b = *(const entity_render_t **)bp;
7266
7267         // 1. compare model
7268         if(a->model < b->model)
7269                 return -1;
7270         if(a->model > b->model)
7271                 return +1;
7272
7273         // 2. compare skin
7274         // TODO possibly calculate the REAL skinnum here first using
7275         // skinscenes?
7276         if(a->skinnum < b->skinnum)
7277                 return -1;
7278         if(a->skinnum > b->skinnum)
7279                 return +1;
7280
7281         // everything we compared is equal
7282         return 0;
7283 }
7284 static void R_SortEntities(void)
7285 {
7286         // below or equal 2 ents, sorting never gains anything
7287         if(r_refdef.scene.numentities <= 2)
7288                 return;
7289         // sort
7290         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7291 }
7292
7293 /*
7294 ================
7295 R_RenderView
7296 ================
7297 */
7298 int dpsoftrast_test;
7299 extern cvar_t r_shadow_bouncegrid;
7300 void R_RenderView(void)
7301 {
7302         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7303         int fbo;
7304         rtexture_t *depthtexture;
7305         rtexture_t *colortexture;
7306
7307         dpsoftrast_test = r_test.integer;
7308
7309         if (r_timereport_active)
7310                 R_TimeReport("start");
7311         r_textureframe++; // used only by R_GetCurrentTexture
7312         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7313
7314         if(R_CompileShader_CheckStaticParms())
7315                 R_GLSL_Restart_f();
7316
7317         if (!r_drawentities.integer)
7318                 r_refdef.scene.numentities = 0;
7319         else if (r_sortentities.integer)
7320                 R_SortEntities();
7321
7322         R_AnimCache_ClearCache();
7323
7324         /* adjust for stereo display */
7325         if(R_Stereo_Active())
7326         {
7327                 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);
7328                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7329         }
7330
7331         if (r_refdef.view.isoverlay)
7332         {
7333                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7334                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7335                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7336                 R_TimeReport("depthclear");
7337
7338                 r_refdef.view.showdebug = false;
7339
7340                 r_fb.water.enabled = false;
7341                 r_fb.water.numwaterplanes = 0;
7342
7343                 R_RenderScene(0, NULL, NULL);
7344
7345                 r_refdef.view.matrix = originalmatrix;
7346
7347                 CHECKGLERROR
7348                 return;
7349         }
7350
7351         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7352         {
7353                 r_refdef.view.matrix = originalmatrix;
7354                 return;
7355         }
7356
7357         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7358
7359         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7360                 // in sRGB fallback, behave similar to true sRGB: convert this
7361                 // value from linear to sRGB
7362                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7363
7364         R_RenderView_UpdateViewVectors();
7365
7366         R_Shadow_UpdateWorldLightSelection();
7367
7368         R_Bloom_StartFrame();
7369
7370         // apply bloom brightness offset
7371         if(r_fb.bloomtexture[0])
7372                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7373
7374         R_Water_StartFrame();
7375
7376         // now we probably have an fbo to render into
7377         fbo = r_fb.fbo;
7378         depthtexture = r_fb.depthtexture;
7379         colortexture = r_fb.colortexture;
7380
7381         CHECKGLERROR
7382         if (r_timereport_active)
7383                 R_TimeReport("viewsetup");
7384
7385         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7386
7387         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7388         {
7389                 R_ClearScreen(r_refdef.fogenabled);
7390                 if (r_timereport_active)
7391                         R_TimeReport("viewclear");
7392         }
7393         r_refdef.view.clear = true;
7394
7395         r_refdef.view.showdebug = true;
7396
7397         R_View_Update();
7398         if (r_timereport_active)
7399                 R_TimeReport("visibility");
7400
7401         R_AnimCache_CacheVisibleEntities();
7402         if (r_timereport_active)
7403                 R_TimeReport("animcache");
7404
7405         R_Shadow_UpdateBounceGridTexture();
7406         if (r_timereport_active && r_shadow_bouncegrid.integer)
7407                 R_TimeReport("bouncegrid");
7408
7409         r_fb.water.numwaterplanes = 0;
7410         if (r_fb.water.enabled)
7411                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7412
7413         R_RenderScene(fbo, depthtexture, colortexture);
7414         r_fb.water.numwaterplanes = 0;
7415
7416         R_BlendView(fbo, depthtexture, colortexture);
7417         if (r_timereport_active)
7418                 R_TimeReport("blendview");
7419
7420         GL_Scissor(0, 0, vid.width, vid.height);
7421         GL_ScissorTest(false);
7422
7423         r_refdef.view.matrix = originalmatrix;
7424
7425         CHECKGLERROR
7426 }
7427
7428 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7429 {
7430         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7431         {
7432                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7433                 if (r_timereport_active)
7434                         R_TimeReport("waterworld");
7435         }
7436
7437         // don't let sound skip if going slow
7438         if (r_refdef.scene.extraupdate)
7439                 S_ExtraUpdate ();
7440
7441         R_DrawModelsAddWaterPlanes();
7442         if (r_timereport_active)
7443                 R_TimeReport("watermodels");
7444
7445         if (r_fb.water.numwaterplanes)
7446         {
7447                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7448                 if (r_timereport_active)
7449                         R_TimeReport("waterscenes");
7450         }
7451 }
7452
7453 extern cvar_t cl_locs_show;
7454 static void R_DrawLocs(void);
7455 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7456 static void R_DrawModelDecals(void);
7457 extern cvar_t cl_decals_newsystem;
7458 extern qboolean r_shadow_usingdeferredprepass;
7459 extern int r_shadow_shadowmapatlas_modelshadows_size;
7460 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7461 {
7462         qboolean shadowmapping = false;
7463
7464         if (r_timereport_active)
7465                 R_TimeReport("beginscene");
7466
7467         r_refdef.stats[r_stat_renders]++;
7468
7469         R_UpdateFog();
7470
7471         // don't let sound skip if going slow
7472         if (r_refdef.scene.extraupdate)
7473                 S_ExtraUpdate ();
7474
7475         R_MeshQueue_BeginScene();
7476
7477         R_SkyStartFrame();
7478
7479         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);
7480
7481         if (r_timereport_active)
7482                 R_TimeReport("skystartframe");
7483
7484         if (cl.csqc_vidvars.drawworld)
7485         {
7486                 // don't let sound skip if going slow
7487                 if (r_refdef.scene.extraupdate)
7488                         S_ExtraUpdate ();
7489
7490                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7491                 {
7492                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7493                         if (r_timereport_active)
7494                                 R_TimeReport("worldsky");
7495                 }
7496
7497                 if (R_DrawBrushModelsSky() && r_timereport_active)
7498                         R_TimeReport("bmodelsky");
7499
7500                 if (skyrendermasked && skyrenderlater)
7501                 {
7502                         // we have to force off the water clipping plane while rendering sky
7503                         R_SetupView(false, fbo, depthtexture, colortexture);
7504                         R_Sky();
7505                         R_SetupView(true, fbo, depthtexture, colortexture);
7506                         if (r_timereport_active)
7507                                 R_TimeReport("sky");
7508                 }
7509         }
7510
7511         R_Shadow_PrepareModelShadows();
7512         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7513         if (r_timereport_active)
7514                 R_TimeReport("preparelights");
7515
7516         // render all the shadowmaps that will be used for this view
7517         shadowmapping = R_Shadow_ShadowMappingEnabled();
7518         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7519         {
7520                 R_Shadow_DrawShadowMaps();
7521                 if (r_timereport_active)
7522                         R_TimeReport("shadowmaps");
7523         }
7524
7525         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7526         if (r_shadow_usingdeferredprepass)
7527                 R_Shadow_DrawPrepass();
7528
7529         // now we begin the forward pass of the view render
7530         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7531         {
7532                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7533                 if (r_timereport_active)
7534                         R_TimeReport("worlddepth");
7535         }
7536         if (r_depthfirst.integer >= 2)
7537         {
7538                 R_DrawModelsDepth();
7539                 if (r_timereport_active)
7540                         R_TimeReport("modeldepth");
7541         }
7542
7543         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7544         {
7545                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7546                 if (r_timereport_active)
7547                         R_TimeReport("world");
7548         }
7549
7550         // don't let sound skip if going slow
7551         if (r_refdef.scene.extraupdate)
7552                 S_ExtraUpdate ();
7553
7554         R_DrawModels();
7555         if (r_timereport_active)
7556                 R_TimeReport("models");
7557
7558         // don't let sound skip if going slow
7559         if (r_refdef.scene.extraupdate)
7560                 S_ExtraUpdate ();
7561
7562         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7563         {
7564                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7565                 R_Shadow_DrawModelShadows();
7566                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7567                 // don't let sound skip if going slow
7568                 if (r_refdef.scene.extraupdate)
7569                         S_ExtraUpdate ();
7570         }
7571
7572         if (!r_shadow_usingdeferredprepass)
7573         {
7574                 R_Shadow_DrawLights();
7575                 if (r_timereport_active)
7576                         R_TimeReport("rtlights");
7577         }
7578
7579         // don't let sound skip if going slow
7580         if (r_refdef.scene.extraupdate)
7581                 S_ExtraUpdate ();
7582
7583         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7584         {
7585                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7586                 R_Shadow_DrawModelShadows();
7587                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7588                 // don't let sound skip if going slow
7589                 if (r_refdef.scene.extraupdate)
7590                         S_ExtraUpdate ();
7591         }
7592
7593         if (cl.csqc_vidvars.drawworld)
7594         {
7595                 if (cl_decals_newsystem.integer)
7596                 {
7597                         R_DrawModelDecals();
7598                         if (r_timereport_active)
7599                                 R_TimeReport("modeldecals");
7600                 }
7601                 else
7602                 {
7603                         R_DrawDecals();
7604                         if (r_timereport_active)
7605                                 R_TimeReport("decals");
7606                 }
7607
7608                 R_DrawParticles();
7609                 if (r_timereport_active)
7610                         R_TimeReport("particles");
7611
7612                 R_DrawExplosions();
7613                 if (r_timereport_active)
7614                         R_TimeReport("explosions");
7615         }
7616
7617         if (cl.csqc_loaded)
7618                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7619
7620         if (r_refdef.view.showdebug)
7621         {
7622                 if (cl_locs_show.integer)
7623                 {
7624                         R_DrawLocs();
7625                         if (r_timereport_active)
7626                                 R_TimeReport("showlocs");
7627                 }
7628
7629                 if (r_drawportals.integer)
7630                 {
7631                         R_DrawPortals();
7632                         if (r_timereport_active)
7633                                 R_TimeReport("portals");
7634                 }
7635
7636                 if (r_showbboxes_client.value > 0)
7637                 {
7638                         R_DrawEntityBBoxes(CLVM_prog);
7639                         if (r_timereport_active)
7640                                 R_TimeReport("clbboxes");
7641                 }
7642                 if (r_showbboxes.value > 0)
7643                 {
7644                         R_DrawEntityBBoxes(SVVM_prog);
7645                         if (r_timereport_active)
7646                                 R_TimeReport("svbboxes");
7647                 }
7648         }
7649
7650         if (r_transparent.integer)
7651         {
7652                 R_MeshQueue_RenderTransparent();
7653                 if (r_timereport_active)
7654                         R_TimeReport("drawtrans");
7655         }
7656
7657         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))
7658         {
7659                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7660                 if (r_timereport_active)
7661                         R_TimeReport("worlddebug");
7662                 R_DrawModelsDebug();
7663                 if (r_timereport_active)
7664                         R_TimeReport("modeldebug");
7665         }
7666
7667         if (cl.csqc_vidvars.drawworld)
7668         {
7669                 R_Shadow_DrawCoronas();
7670                 if (r_timereport_active)
7671                         R_TimeReport("coronas");
7672         }
7673
7674 #if 0
7675         {
7676                 GL_DepthTest(false);
7677                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7678                 GL_Color(1, 1, 1, 1);
7679                 qglBegin(GL_POLYGON);
7680                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7681                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7682                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7683                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7684                 qglEnd();
7685                 qglBegin(GL_POLYGON);
7686                 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]);
7687                 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]);
7688                 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]);
7689                 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]);
7690                 qglEnd();
7691                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7692         }
7693 #endif
7694
7695         // don't let sound skip if going slow
7696         if (r_refdef.scene.extraupdate)
7697                 S_ExtraUpdate ();
7698 }
7699
7700 static const unsigned short bboxelements[36] =
7701 {
7702         5, 1, 3, 5, 3, 7,
7703         6, 2, 0, 6, 0, 4,
7704         7, 3, 2, 7, 2, 6,
7705         4, 0, 1, 4, 1, 5,
7706         4, 5, 7, 4, 7, 6,
7707         1, 0, 2, 1, 2, 3,
7708 };
7709
7710 #define BBOXEDGES 13
7711 static const float bboxedges[BBOXEDGES][6] = 
7712 {
7713         // whole box
7714         { 0, 0, 0, 1, 1, 1 },
7715         // bottom edges
7716         { 0, 0, 0, 0, 1, 0 },
7717         { 0, 0, 0, 1, 0, 0 },
7718         { 0, 1, 0, 1, 1, 0 },
7719         { 1, 0, 0, 1, 1, 0 },
7720         // top edges
7721         { 0, 0, 1, 0, 1, 1 },
7722         { 0, 0, 1, 1, 0, 1 },
7723         { 0, 1, 1, 1, 1, 1 },
7724         { 1, 0, 1, 1, 1, 1 },
7725         // vertical edges
7726         { 0, 0, 0, 0, 0, 1 },
7727         { 1, 0, 0, 1, 0, 1 },
7728         { 0, 1, 0, 0, 1, 1 },
7729         { 1, 1, 0, 1, 1, 1 },
7730 };
7731
7732 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7733 {
7734         int numvertices = BBOXEDGES * 8;
7735         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7736         int numtriangles = BBOXEDGES * 12;
7737         unsigned short elements[BBOXEDGES * 36];
7738         int i, edge;
7739         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7740
7741         RSurf_ActiveWorldEntity();
7742
7743         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7744         GL_DepthMask(false);
7745         GL_DepthRange(0, 1);
7746         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7747
7748         for (edge = 0; edge < BBOXEDGES; edge++)
7749         {
7750                 for (i = 0; i < 3; i++)
7751                 {
7752                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7753                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7754                 }
7755                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7756                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7757                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7758                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7759                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7760                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7761                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7762                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7763                 for (i = 0; i < 36; i++)
7764                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7765         }
7766         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7767         if (r_refdef.fogenabled)
7768         {
7769                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7770                 {
7771                         f1 = RSurf_FogVertex(v);
7772                         f2 = 1 - f1;
7773                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7774                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7775                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7776                 }
7777         }
7778         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7779         R_Mesh_ResetTextureState();
7780         R_SetupShader_Generic_NoTexture(false, false);
7781         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7782 }
7783
7784 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7785 {
7786         // hacky overloading of the parameters
7787         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7788         int i;
7789         float color[4];
7790         prvm_edict_t *edict;
7791
7792         GL_CullFace(GL_NONE);
7793         R_SetupShader_Generic_NoTexture(false, false);
7794
7795         for (i = 0;i < numsurfaces;i++)
7796         {
7797                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7798                 switch ((int)PRVM_serveredictfloat(edict, solid))
7799                 {
7800                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7801                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7802                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7803                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7804                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7805                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7806                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7807                 }
7808                 if (prog == CLVM_prog)
7809                         color[3] *= r_showbboxes_client.value;
7810                 else
7811                         color[3] *= r_showbboxes.value;
7812                 color[3] = bound(0, color[3], 1);
7813                 GL_DepthTest(!r_showdisabledepthtest.integer);
7814                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7815         }
7816 }
7817
7818 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7819 {
7820         int i;
7821         prvm_edict_t *edict;
7822         vec3_t center;
7823
7824         if (prog == NULL)
7825                 return;
7826
7827         for (i = 0; i < prog->num_edicts; i++)
7828         {
7829                 edict = PRVM_EDICT_NUM(i);
7830                 if (edict->priv.server->free)
7831                         continue;
7832                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7833                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7834                         continue;
7835                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7836                         continue;
7837                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7838                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7839         }
7840 }
7841
7842 static const int nomodelelement3i[24] =
7843 {
7844         5, 2, 0,
7845         5, 1, 2,
7846         5, 0, 3,
7847         5, 3, 1,
7848         0, 2, 4,
7849         2, 1, 4,
7850         3, 0, 4,
7851         1, 3, 4
7852 };
7853
7854 static const unsigned short nomodelelement3s[24] =
7855 {
7856         5, 2, 0,
7857         5, 1, 2,
7858         5, 0, 3,
7859         5, 3, 1,
7860         0, 2, 4,
7861         2, 1, 4,
7862         3, 0, 4,
7863         1, 3, 4
7864 };
7865
7866 static const float nomodelvertex3f[6*3] =
7867 {
7868         -16,   0,   0,
7869          16,   0,   0,
7870           0, -16,   0,
7871           0,  16,   0,
7872           0,   0, -16,
7873           0,   0,  16
7874 };
7875
7876 static const float nomodelcolor4f[6*4] =
7877 {
7878         0.0f, 0.0f, 0.5f, 1.0f,
7879         0.0f, 0.0f, 0.5f, 1.0f,
7880         0.0f, 0.5f, 0.0f, 1.0f,
7881         0.0f, 0.5f, 0.0f, 1.0f,
7882         0.5f, 0.0f, 0.0f, 1.0f,
7883         0.5f, 0.0f, 0.0f, 1.0f
7884 };
7885
7886 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7887 {
7888         int i;
7889         float f1, f2, *c;
7890         float color4f[6*4];
7891
7892         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);
7893
7894         // this is only called once per entity so numsurfaces is always 1, and
7895         // surfacelist is always {0}, so this code does not handle batches
7896
7897         if (rsurface.ent_flags & RENDER_ADDITIVE)
7898         {
7899                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7900                 GL_DepthMask(false);
7901         }
7902         else if (rsurface.colormod[3] < 1)
7903         {
7904                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7905                 GL_DepthMask(false);
7906         }
7907         else
7908         {
7909                 GL_BlendFunc(GL_ONE, GL_ZERO);
7910                 GL_DepthMask(true);
7911         }
7912         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7913         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7914         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7915         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7916         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7917         for (i = 0, c = color4f;i < 6;i++, c += 4)
7918         {
7919                 c[0] *= rsurface.colormod[0];
7920                 c[1] *= rsurface.colormod[1];
7921                 c[2] *= rsurface.colormod[2];
7922                 c[3] *= rsurface.colormod[3];
7923         }
7924         if (r_refdef.fogenabled)
7925         {
7926                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7927                 {
7928                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7929                         f2 = 1 - f1;
7930                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7931                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7932                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7933                 }
7934         }
7935 //      R_Mesh_ResetTextureState();
7936         R_SetupShader_Generic_NoTexture(false, false);
7937         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7938         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7939 }
7940
7941 void R_DrawNoModel(entity_render_t *ent)
7942 {
7943         vec3_t org;
7944         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7945         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7946                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7947         else
7948                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7949 }
7950
7951 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7952 {
7953         vec3_t right1, right2, diff, normal;
7954
7955         VectorSubtract (org2, org1, normal);
7956
7957         // calculate 'right' vector for start
7958         VectorSubtract (r_refdef.view.origin, org1, diff);
7959         CrossProduct (normal, diff, right1);
7960         VectorNormalize (right1);
7961
7962         // calculate 'right' vector for end
7963         VectorSubtract (r_refdef.view.origin, org2, diff);
7964         CrossProduct (normal, diff, right2);
7965         VectorNormalize (right2);
7966
7967         vert[ 0] = org1[0] + width * right1[0];
7968         vert[ 1] = org1[1] + width * right1[1];
7969         vert[ 2] = org1[2] + width * right1[2];
7970         vert[ 3] = org1[0] - width * right1[0];
7971         vert[ 4] = org1[1] - width * right1[1];
7972         vert[ 5] = org1[2] - width * right1[2];
7973         vert[ 6] = org2[0] - width * right2[0];
7974         vert[ 7] = org2[1] - width * right2[1];
7975         vert[ 8] = org2[2] - width * right2[2];
7976         vert[ 9] = org2[0] + width * right2[0];
7977         vert[10] = org2[1] + width * right2[1];
7978         vert[11] = org2[2] + width * right2[2];
7979 }
7980
7981 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)
7982 {
7983         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7984         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7985         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7986         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7987         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7988         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7989         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7990         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7991         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7992         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7993         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7994         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7995 }
7996
7997 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7998 {
7999         int i;
8000         float *vertex3f;
8001         float v[3];
8002         VectorSet(v, x, y, z);
8003         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8004                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8005                         break;
8006         if (i == mesh->numvertices)
8007         {
8008                 if (mesh->numvertices < mesh->maxvertices)
8009                 {
8010                         VectorCopy(v, vertex3f);
8011                         mesh->numvertices++;
8012                 }
8013                 return mesh->numvertices;
8014         }
8015         else
8016                 return i;
8017 }
8018
8019 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8020 {
8021         int i;
8022         int *e, element[3];
8023         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8024         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8025         e = mesh->element3i + mesh->numtriangles * 3;
8026         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8027         {
8028                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8029                 if (mesh->numtriangles < mesh->maxtriangles)
8030                 {
8031                         *e++ = element[0];
8032                         *e++ = element[1];
8033                         *e++ = element[2];
8034                         mesh->numtriangles++;
8035                 }
8036                 element[1] = element[2];
8037         }
8038 }
8039
8040 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8041 {
8042         int i;
8043         int *e, element[3];
8044         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8045         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8046         e = mesh->element3i + mesh->numtriangles * 3;
8047         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8048         {
8049                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8050                 if (mesh->numtriangles < mesh->maxtriangles)
8051                 {
8052                         *e++ = element[0];
8053                         *e++ = element[1];
8054                         *e++ = element[2];
8055                         mesh->numtriangles++;
8056                 }
8057                 element[1] = element[2];
8058         }
8059 }
8060
8061 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8062 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8063 {
8064         int planenum, planenum2;
8065         int w;
8066         int tempnumpoints;
8067         mplane_t *plane, *plane2;
8068         double maxdist;
8069         double temppoints[2][256*3];
8070         // figure out how large a bounding box we need to properly compute this brush
8071         maxdist = 0;
8072         for (w = 0;w < numplanes;w++)
8073                 maxdist = max(maxdist, fabs(planes[w].dist));
8074         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8075         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8076         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8077         {
8078                 w = 0;
8079                 tempnumpoints = 4;
8080                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8081                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8082                 {
8083                         if (planenum2 == planenum)
8084                                 continue;
8085                         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);
8086                         w = !w;
8087                 }
8088                 if (tempnumpoints < 3)
8089                         continue;
8090                 // generate elements forming a triangle fan for this polygon
8091                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8092         }
8093 }
8094
8095 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)
8096 {
8097         texturelayer_t *layer;
8098         layer = t->currentlayers + t->currentnumlayers++;
8099         layer->type = type;
8100         layer->depthmask = depthmask;
8101         layer->blendfunc1 = blendfunc1;
8102         layer->blendfunc2 = blendfunc2;
8103         layer->texture = texture;
8104         layer->texmatrix = *matrix;
8105         layer->color[0] = r;
8106         layer->color[1] = g;
8107         layer->color[2] = b;
8108         layer->color[3] = a;
8109 }
8110
8111 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8112 {
8113         if(parms[0] == 0 && parms[1] == 0)
8114                 return false;
8115         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8116                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8117                         return false;
8118         return true;
8119 }
8120
8121 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8122 {
8123         double index, f;
8124         index = parms[2] + rsurface.shadertime * parms[3];
8125         index -= floor(index);
8126         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8127         {
8128         default:
8129         case Q3WAVEFUNC_NONE:
8130         case Q3WAVEFUNC_NOISE:
8131         case Q3WAVEFUNC_COUNT:
8132                 f = 0;
8133                 break;
8134         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8135         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8136         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8137         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8138         case Q3WAVEFUNC_TRIANGLE:
8139                 index *= 4;
8140                 f = index - floor(index);
8141                 if (index < 1)
8142                 {
8143                         // f = f;
8144                 }
8145                 else if (index < 2)
8146                         f = 1 - f;
8147                 else if (index < 3)
8148                         f = -f;
8149                 else
8150                         f = -(1 - f);
8151                 break;
8152         }
8153         f = parms[0] + parms[1] * f;
8154         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8155                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8156         return (float) f;
8157 }
8158
8159 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8160 {
8161         int w, h, idx;
8162         float shadertime;
8163         float f;
8164         float offsetd[2];
8165         float tcmat[12];
8166         matrix4x4_t matrix, temp;
8167         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8168         // it's better to have one huge fixup every 9 hours than gradual
8169         // degradation over time which looks consistently bad after many hours.
8170         //
8171         // tcmod scroll in particular suffers from this degradation which can't be
8172         // effectively worked around even with floor() tricks because we don't
8173         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8174         // a workaround involving floor() would be incorrect anyway...
8175         shadertime = rsurface.shadertime;
8176         if (shadertime >= 32768.0f)
8177                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8178         switch(tcmod->tcmod)
8179         {
8180                 case Q3TCMOD_COUNT:
8181                 case Q3TCMOD_NONE:
8182                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8183                                 matrix = r_waterscrollmatrix;
8184                         else
8185                                 matrix = identitymatrix;
8186                         break;
8187                 case Q3TCMOD_ENTITYTRANSLATE:
8188                         // this is used in Q3 to allow the gamecode to control texcoord
8189                         // scrolling on the entity, which is not supported in darkplaces yet.
8190                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8191                         break;
8192                 case Q3TCMOD_ROTATE:
8193                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8194                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8195                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8196                         break;
8197                 case Q3TCMOD_SCALE:
8198                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8199                         break;
8200                 case Q3TCMOD_SCROLL:
8201                         // this particular tcmod is a "bug for bug" compatible one with regards to
8202                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8203                         // specifically did the wrapping and so we must mimic that...
8204                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8205                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8206                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8207                         break;
8208                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8209                         w = (int) tcmod->parms[0];
8210                         h = (int) tcmod->parms[1];
8211                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8212                         f = f - floor(f);
8213                         idx = (int) floor(f * w * h);
8214                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8215                         break;
8216                 case Q3TCMOD_STRETCH:
8217                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8218                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8219                         break;
8220                 case Q3TCMOD_TRANSFORM:
8221                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8222                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8223                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8224                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8225                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8226                         break;
8227                 case Q3TCMOD_TURBULENT:
8228                         // this is handled in the RSurf_PrepareVertices function
8229                         matrix = identitymatrix;
8230                         break;
8231         }
8232         temp = *texmatrix;
8233         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8234 }
8235
8236 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8237 {
8238         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8239         char name[MAX_QPATH];
8240         skinframe_t *skinframe;
8241         unsigned char pixels[296*194];
8242         strlcpy(cache->name, skinname, sizeof(cache->name));
8243         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8244         if (developer_loading.integer)
8245                 Con_Printf("loading %s\n", name);
8246         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8247         if (!skinframe || !skinframe->base)
8248         {
8249                 unsigned char *f;
8250                 fs_offset_t filesize;
8251                 skinframe = NULL;
8252                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8253                 if (f)
8254                 {
8255                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8256                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8257                         Mem_Free(f);
8258                 }
8259         }
8260         cache->skinframe = skinframe;
8261 }
8262
8263 texture_t *R_GetCurrentTexture(texture_t *t)
8264 {
8265         int i;
8266         const entity_render_t *ent = rsurface.entity;
8267         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8268         q3shaderinfo_layer_tcmod_t *tcmod;
8269
8270         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8271                 return t->currentframe;
8272         t->update_lastrenderframe = r_textureframe;
8273         t->update_lastrenderentity = (void *)ent;
8274
8275         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8276                 t->camera_entity = ent->entitynumber;
8277         else
8278                 t->camera_entity = 0;
8279
8280         // switch to an alternate material if this is a q1bsp animated material
8281         {
8282                 texture_t *texture = t;
8283                 int s = rsurface.ent_skinnum;
8284                 if ((unsigned int)s >= (unsigned int)model->numskins)
8285                         s = 0;
8286                 if (model->skinscenes)
8287                 {
8288                         if (model->skinscenes[s].framecount > 1)
8289                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8290                         else
8291                                 s = model->skinscenes[s].firstframe;
8292                 }
8293                 if (s > 0)
8294                         t = t + s * model->num_surfaces;
8295                 if (t->animated)
8296                 {
8297                         // use an alternate animation if the entity's frame is not 0,
8298                         // and only if the texture has an alternate animation
8299                         if (t->animated == 2) // q2bsp
8300                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8301                         else if (rsurface.ent_alttextures && t->anim_total[1])
8302                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8303                         else
8304                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8305                 }
8306                 texture->currentframe = t;
8307         }
8308
8309         // update currentskinframe to be a qw skin or animation frame
8310         if (rsurface.ent_qwskin >= 0)
8311         {
8312                 i = rsurface.ent_qwskin;
8313                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8314                 {
8315                         r_qwskincache_size = cl.maxclients;
8316                         if (r_qwskincache)
8317                                 Mem_Free(r_qwskincache);
8318                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8319                 }
8320                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8321                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8322                 t->currentskinframe = r_qwskincache[i].skinframe;
8323                 if (t->materialshaderpass && t->currentskinframe == NULL)
8324                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8325         }
8326         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8327                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8328         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8329                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8330
8331         t->currentmaterialflags = t->basematerialflags;
8332         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8333         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8334                 t->currentalpha *= r_wateralpha.value;
8335         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8336                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8337         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8338                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8339         if (!(rsurface.ent_flags & RENDER_LIGHT))
8340                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8341         else if (FAKELIGHT_ENABLED)
8342         {
8343                 // no modellight if using fakelight for the map
8344         }
8345         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8346         {
8347                 // pick a model lighting mode
8348                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8349                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8350                 else
8351                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8352         }
8353         if (rsurface.ent_flags & RENDER_ADDITIVE)
8354                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8355         else if (t->currentalpha < 1)
8356                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8357         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8358         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8359                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8360         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8361                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8362         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8363                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8364         if (t->backgroundshaderpass)
8365                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8366         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8367         {
8368                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8369                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8370         }
8371         else
8372                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8373         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8374         {
8375                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8376                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8377         }
8378         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8379                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8380
8381         // there is no tcmod
8382         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8383         {
8384                 t->currenttexmatrix = r_waterscrollmatrix;
8385                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8386         }
8387         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8388         {
8389                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8390                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8391         }
8392
8393         if (t->materialshaderpass)
8394                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8395                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8396
8397         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8398         if (t->currentskinframe->qpixels)
8399                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8400         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8401         if (!t->basetexture)
8402                 t->basetexture = r_texture_notexture;
8403         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8404         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8405         t->nmaptexture = t->currentskinframe->nmap;
8406         if (!t->nmaptexture)
8407                 t->nmaptexture = r_texture_blanknormalmap;
8408         t->glosstexture = r_texture_black;
8409         t->glowtexture = t->currentskinframe->glow;
8410         t->fogtexture = t->currentskinframe->fog;
8411         t->reflectmasktexture = t->currentskinframe->reflect;
8412         if (t->backgroundshaderpass)
8413         {
8414                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8415                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8416                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8417                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8418                 t->backgroundglosstexture = r_texture_black;
8419                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8420                 if (!t->backgroundnmaptexture)
8421                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8422                 // make sure that if glow is going to be used, both textures are not NULL
8423                 if (!t->backgroundglowtexture && t->glowtexture)
8424                         t->backgroundglowtexture = r_texture_black;
8425                 if (!t->glowtexture && t->backgroundglowtexture)
8426                         t->glowtexture = r_texture_black;
8427         }
8428         else
8429         {
8430                 t->backgroundbasetexture = r_texture_white;
8431                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8432                 t->backgroundglosstexture = r_texture_black;
8433                 t->backgroundglowtexture = NULL;
8434         }
8435         t->specularpower = r_shadow_glossexponent.value;
8436         // TODO: store reference values for these in the texture?
8437         t->specularscale = 0;
8438         if (r_shadow_gloss.integer > 0)
8439         {
8440                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8441                 {
8442                         if (r_shadow_glossintensity.value > 0)
8443                         {
8444                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8445                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8446                                 t->specularscale = r_shadow_glossintensity.value;
8447                         }
8448                 }
8449                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8450                 {
8451                         t->glosstexture = r_texture_white;
8452                         t->backgroundglosstexture = r_texture_white;
8453                         t->specularscale = r_shadow_gloss2intensity.value;
8454                         t->specularpower = r_shadow_gloss2exponent.value;
8455                 }
8456         }
8457         t->specularscale *= t->specularscalemod;
8458         t->specularpower *= t->specularpowermod;
8459         t->rtlightambient = 0;
8460
8461         // lightmaps mode looks bad with dlights using actual texturing, so turn
8462         // off the colormap and glossmap, but leave the normalmap on as it still
8463         // accurately represents the shading involved
8464         if (gl_lightmaps.integer)
8465         {
8466                 t->basetexture = r_texture_grey128;
8467                 t->pantstexture = r_texture_black;
8468                 t->shirttexture = r_texture_black;
8469                 if (gl_lightmaps.integer < 2)
8470                         t->nmaptexture = r_texture_blanknormalmap;
8471                 t->glosstexture = r_texture_black;
8472                 t->glowtexture = NULL;
8473                 t->fogtexture = NULL;
8474                 t->reflectmasktexture = NULL;
8475                 t->backgroundbasetexture = NULL;
8476                 if (gl_lightmaps.integer < 2)
8477                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8478                 t->backgroundglosstexture = r_texture_black;
8479                 t->backgroundglowtexture = NULL;
8480                 t->specularscale = 0;
8481                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8482         }
8483
8484         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8485         VectorClear(t->dlightcolor);
8486         t->currentnumlayers = 0;
8487         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8488         {
8489                 int blendfunc1, blendfunc2;
8490                 qboolean depthmask;
8491                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8492                 {
8493                         blendfunc1 = GL_SRC_ALPHA;
8494                         blendfunc2 = GL_ONE;
8495                 }
8496                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8497                 {
8498                         blendfunc1 = GL_SRC_ALPHA;
8499                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8500                 }
8501                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8502                 {
8503                         blendfunc1 = t->customblendfunc[0];
8504                         blendfunc2 = t->customblendfunc[1];
8505                 }
8506                 else
8507                 {
8508                         blendfunc1 = GL_ONE;
8509                         blendfunc2 = GL_ZERO;
8510                 }
8511                 // don't colormod evilblend textures
8512                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8513                         VectorSet(t->lightmapcolor, 1, 1, 1);
8514                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8515                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8516                 {
8517                         // fullbright is not affected by r_refdef.lightmapintensity
8518                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8519                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8520                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8521                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8522                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8523                 }
8524                 else
8525                 {
8526                         vec3_t ambientcolor;
8527                         float colorscale;
8528                         // set the color tint used for lights affecting this surface
8529                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8530                         colorscale = 2;
8531                         // q3bsp has no lightmap updates, so the lightstylevalue that
8532                         // would normally be baked into the lightmap must be
8533                         // applied to the color
8534                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8535                         if (model->type == mod_brushq3)
8536                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8537                         colorscale *= r_refdef.lightmapintensity;
8538                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8539                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8540                         // basic lit geometry
8541                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8542                         // add pants/shirt if needed
8543                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8544                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8545                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8546                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8547                         // now add ambient passes if needed
8548                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8549                         {
8550                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8551                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8552                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8553                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8554                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8555                         }
8556                 }
8557                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8558                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8559                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8560                 {
8561                         // if this is opaque use alpha blend which will darken the earlier
8562                         // passes cheaply.
8563                         //
8564                         // if this is an alpha blended material, all the earlier passes
8565                         // were darkened by fog already, so we only need to add the fog
8566                         // color ontop through the fog mask texture
8567                         //
8568                         // if this is an additive blended material, all the earlier passes
8569                         // were darkened by fog already, and we should not add fog color
8570                         // (because the background was not darkened, there is no fog color
8571                         // that was lost behind it).
8572                         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->lightmapcolor[3]);
8573                 }
8574         }
8575
8576         return t;
8577 }
8578
8579 rsurfacestate_t rsurface;
8580
8581 void RSurf_ActiveWorldEntity(void)
8582 {
8583         dp_model_t *model = r_refdef.scene.worldmodel;
8584         //if (rsurface.entity == r_refdef.scene.worldentity)
8585         //      return;
8586         rsurface.entity = r_refdef.scene.worldentity;
8587         rsurface.skeleton = NULL;
8588         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8589         rsurface.ent_skinnum = 0;
8590         rsurface.ent_qwskin = -1;
8591         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8592         rsurface.shadertime = r_refdef.scene.time;
8593         rsurface.matrix = identitymatrix;
8594         rsurface.inversematrix = identitymatrix;
8595         rsurface.matrixscale = 1;
8596         rsurface.inversematrixscale = 1;
8597         R_EntityMatrix(&identitymatrix);
8598         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8599         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8600         rsurface.fograngerecip = r_refdef.fograngerecip;
8601         rsurface.fogheightfade = r_refdef.fogheightfade;
8602         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8603         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8604         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8605         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8606         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8607         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8608         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8609         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8610         rsurface.colormod[3] = 1;
8611         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8612         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8613         rsurface.frameblend[0].lerp = 1;
8614         rsurface.ent_alttextures = false;
8615         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8616         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8617         rsurface.entityskeletaltransform3x4 = NULL;
8618         rsurface.entityskeletaltransform3x4buffer = NULL;
8619         rsurface.entityskeletaltransform3x4offset = 0;
8620         rsurface.entityskeletaltransform3x4size = 0;;
8621         rsurface.entityskeletalnumtransforms = 0;
8622         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8623         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8624         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8625         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8626         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8627         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8628         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8629         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8630         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8631         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8632         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8633         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8634         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8635         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8636         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8637         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8638         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8639         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8640         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8641         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8642         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8643         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8644         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8645         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8646         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8647         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8648         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8649         rsurface.modelelement3i = model->surfmesh.data_element3i;
8650         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8651         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8652         rsurface.modelelement3s = model->surfmesh.data_element3s;
8653         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8654         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8655         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8656         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8657         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8658         rsurface.modelsurfaces = model->data_surfaces;
8659         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8660         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8661         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8662         rsurface.modelgeneratedvertex = false;
8663         rsurface.batchgeneratedvertex = false;
8664         rsurface.batchfirstvertex = 0;
8665         rsurface.batchnumvertices = 0;
8666         rsurface.batchfirsttriangle = 0;
8667         rsurface.batchnumtriangles = 0;
8668         rsurface.batchvertex3f  = NULL;
8669         rsurface.batchvertex3f_vertexbuffer = NULL;
8670         rsurface.batchvertex3f_bufferoffset = 0;
8671         rsurface.batchsvector3f = NULL;
8672         rsurface.batchsvector3f_vertexbuffer = NULL;
8673         rsurface.batchsvector3f_bufferoffset = 0;
8674         rsurface.batchtvector3f = NULL;
8675         rsurface.batchtvector3f_vertexbuffer = NULL;
8676         rsurface.batchtvector3f_bufferoffset = 0;
8677         rsurface.batchnormal3f  = NULL;
8678         rsurface.batchnormal3f_vertexbuffer = NULL;
8679         rsurface.batchnormal3f_bufferoffset = 0;
8680         rsurface.batchlightmapcolor4f = NULL;
8681         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8682         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8683         rsurface.batchtexcoordtexture2f = NULL;
8684         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8685         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8686         rsurface.batchtexcoordlightmap2f = NULL;
8687         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8688         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8689         rsurface.batchskeletalindex4ub = NULL;
8690         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8691         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8692         rsurface.batchskeletalweight4ub = NULL;
8693         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8694         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8695         rsurface.batchvertexmesh = NULL;
8696         rsurface.batchvertexmesh_vertexbuffer = NULL;
8697         rsurface.batchvertexmesh_bufferoffset = 0;
8698         rsurface.batchelement3i = NULL;
8699         rsurface.batchelement3i_indexbuffer = NULL;
8700         rsurface.batchelement3i_bufferoffset = 0;
8701         rsurface.batchelement3s = NULL;
8702         rsurface.batchelement3s_indexbuffer = NULL;
8703         rsurface.batchelement3s_bufferoffset = 0;
8704         rsurface.passcolor4f = NULL;
8705         rsurface.passcolor4f_vertexbuffer = NULL;
8706         rsurface.passcolor4f_bufferoffset = 0;
8707         rsurface.forcecurrenttextureupdate = false;
8708 }
8709
8710 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8711 {
8712         dp_model_t *model = ent->model;
8713         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8714         //      return;
8715         rsurface.entity = (entity_render_t *)ent;
8716         rsurface.skeleton = ent->skeleton;
8717         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8718         rsurface.ent_skinnum = ent->skinnum;
8719         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;
8720         rsurface.ent_flags = ent->flags;
8721         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8722         rsurface.matrix = ent->matrix;
8723         rsurface.inversematrix = ent->inversematrix;
8724         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8725         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8726         R_EntityMatrix(&rsurface.matrix);
8727         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8728         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8729         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8730         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8731         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8732         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8733         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8734         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8735         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8736         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8737         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8738         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8739         rsurface.colormod[3] = ent->alpha;
8740         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8741         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8742         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8743         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8744         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8745         if (ent->model->brush.submodel && !prepass)
8746         {
8747                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8748                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8749         }
8750         // if the animcache code decided it should use the shader path, skip the deform step
8751         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8752         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8753         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8754         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8755         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8756         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8757         {
8758                 if (ent->animcache_vertex3f)
8759                 {
8760                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8761                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8762                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8763                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8764                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8765                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8766                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8767                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8768                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8769                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8770                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8771                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8772                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8773                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8774                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8775                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8776                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8777                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8778                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8779                 }
8780                 else if (wanttangents)
8781                 {
8782                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8783                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8784                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8785                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8786                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8787                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8788                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8789                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8790                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8791                         rsurface.modelvertexmesh = NULL;
8792                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8793                         rsurface.modelvertexmesh_bufferoffset = 0;
8794                         rsurface.modelvertex3f_vertexbuffer = NULL;
8795                         rsurface.modelvertex3f_bufferoffset = 0;
8796                         rsurface.modelvertex3f_vertexbuffer = 0;
8797                         rsurface.modelvertex3f_bufferoffset = 0;
8798                         rsurface.modelsvector3f_vertexbuffer = 0;
8799                         rsurface.modelsvector3f_bufferoffset = 0;
8800                         rsurface.modeltvector3f_vertexbuffer = 0;
8801                         rsurface.modeltvector3f_bufferoffset = 0;
8802                         rsurface.modelnormal3f_vertexbuffer = 0;
8803                         rsurface.modelnormal3f_bufferoffset = 0;
8804                 }
8805                 else if (wantnormals)
8806                 {
8807                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8808                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8809                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8810                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8811                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8812                         rsurface.modelsvector3f = NULL;
8813                         rsurface.modeltvector3f = NULL;
8814                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8815                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8816                         rsurface.modelvertexmesh = NULL;
8817                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8818                         rsurface.modelvertexmesh_bufferoffset = 0;
8819                         rsurface.modelvertex3f_vertexbuffer = NULL;
8820                         rsurface.modelvertex3f_bufferoffset = 0;
8821                         rsurface.modelvertex3f_vertexbuffer = 0;
8822                         rsurface.modelvertex3f_bufferoffset = 0;
8823                         rsurface.modelsvector3f_vertexbuffer = 0;
8824                         rsurface.modelsvector3f_bufferoffset = 0;
8825                         rsurface.modeltvector3f_vertexbuffer = 0;
8826                         rsurface.modeltvector3f_bufferoffset = 0;
8827                         rsurface.modelnormal3f_vertexbuffer = 0;
8828                         rsurface.modelnormal3f_bufferoffset = 0;
8829                 }
8830                 else
8831                 {
8832                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8833                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8834                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8835                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8836                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8837                         rsurface.modelsvector3f = NULL;
8838                         rsurface.modeltvector3f = NULL;
8839                         rsurface.modelnormal3f = NULL;
8840                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8841                         rsurface.modelvertexmesh = NULL;
8842                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8843                         rsurface.modelvertexmesh_bufferoffset = 0;
8844                         rsurface.modelvertex3f_vertexbuffer = NULL;
8845                         rsurface.modelvertex3f_bufferoffset = 0;
8846                         rsurface.modelvertex3f_vertexbuffer = 0;
8847                         rsurface.modelvertex3f_bufferoffset = 0;
8848                         rsurface.modelsvector3f_vertexbuffer = 0;
8849                         rsurface.modelsvector3f_bufferoffset = 0;
8850                         rsurface.modeltvector3f_vertexbuffer = 0;
8851                         rsurface.modeltvector3f_bufferoffset = 0;
8852                         rsurface.modelnormal3f_vertexbuffer = 0;
8853                         rsurface.modelnormal3f_bufferoffset = 0;
8854                 }
8855                 rsurface.modelgeneratedvertex = true;
8856         }
8857         else
8858         {
8859                 if (rsurface.entityskeletaltransform3x4)
8860                 {
8861                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8862                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8863                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8864                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8865                 }
8866                 else
8867                 {
8868                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8869                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8870                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8871                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8872                 }
8873                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8874                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8875                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8876                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8877                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8878                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8879                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8880                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8881                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8882                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8883                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8884                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8885                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8886                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8887                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8888                 rsurface.modelgeneratedvertex = false;
8889         }
8890         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8891         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8892         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8893         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8894         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8895         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8896         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8897         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8898         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8899         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8900         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8901         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8902         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8903         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8904         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8905         rsurface.modelelement3i = model->surfmesh.data_element3i;
8906         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8907         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8908         rsurface.modelelement3s = model->surfmesh.data_element3s;
8909         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8910         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8911         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8912         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8913         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8914         rsurface.modelsurfaces = model->data_surfaces;
8915         rsurface.batchgeneratedvertex = false;
8916         rsurface.batchfirstvertex = 0;
8917         rsurface.batchnumvertices = 0;
8918         rsurface.batchfirsttriangle = 0;
8919         rsurface.batchnumtriangles = 0;
8920         rsurface.batchvertex3f  = NULL;
8921         rsurface.batchvertex3f_vertexbuffer = NULL;
8922         rsurface.batchvertex3f_bufferoffset = 0;
8923         rsurface.batchsvector3f = NULL;
8924         rsurface.batchsvector3f_vertexbuffer = NULL;
8925         rsurface.batchsvector3f_bufferoffset = 0;
8926         rsurface.batchtvector3f = NULL;
8927         rsurface.batchtvector3f_vertexbuffer = NULL;
8928         rsurface.batchtvector3f_bufferoffset = 0;
8929         rsurface.batchnormal3f  = NULL;
8930         rsurface.batchnormal3f_vertexbuffer = NULL;
8931         rsurface.batchnormal3f_bufferoffset = 0;
8932         rsurface.batchlightmapcolor4f = NULL;
8933         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8934         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8935         rsurface.batchtexcoordtexture2f = NULL;
8936         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8937         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8938         rsurface.batchtexcoordlightmap2f = NULL;
8939         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8940         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8941         rsurface.batchskeletalindex4ub = NULL;
8942         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8943         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8944         rsurface.batchskeletalweight4ub = NULL;
8945         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8946         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8947         rsurface.batchvertexmesh = NULL;
8948         rsurface.batchvertexmesh_vertexbuffer = NULL;
8949         rsurface.batchvertexmesh_bufferoffset = 0;
8950         rsurface.batchelement3i = NULL;
8951         rsurface.batchelement3i_indexbuffer = NULL;
8952         rsurface.batchelement3i_bufferoffset = 0;
8953         rsurface.batchelement3s = NULL;
8954         rsurface.batchelement3s_indexbuffer = NULL;
8955         rsurface.batchelement3s_bufferoffset = 0;
8956         rsurface.passcolor4f = NULL;
8957         rsurface.passcolor4f_vertexbuffer = NULL;
8958         rsurface.passcolor4f_bufferoffset = 0;
8959         rsurface.forcecurrenttextureupdate = false;
8960 }
8961
8962 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)
8963 {
8964         rsurface.entity = r_refdef.scene.worldentity;
8965         rsurface.skeleton = NULL;
8966         rsurface.ent_skinnum = 0;
8967         rsurface.ent_qwskin = -1;
8968         rsurface.ent_flags = entflags;
8969         rsurface.shadertime = r_refdef.scene.time - shadertime;
8970         rsurface.modelnumvertices = numvertices;
8971         rsurface.modelnumtriangles = numtriangles;
8972         rsurface.matrix = *matrix;
8973         rsurface.inversematrix = *inversematrix;
8974         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8975         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8976         R_EntityMatrix(&rsurface.matrix);
8977         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8978         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8979         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8980         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8981         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8982         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8983         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8984         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8985         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8986         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8987         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8988         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8989         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8990         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8991         rsurface.frameblend[0].lerp = 1;
8992         rsurface.ent_alttextures = false;
8993         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8994         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8995         rsurface.entityskeletaltransform3x4 = NULL;
8996         rsurface.entityskeletaltransform3x4buffer = NULL;
8997         rsurface.entityskeletaltransform3x4offset = 0;
8998         rsurface.entityskeletaltransform3x4size = 0;
8999         rsurface.entityskeletalnumtransforms = 0;
9000         r_refdef.stats[r_stat_batch_entitycustom_count]++;
9001         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9002         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9003         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9004         if (wanttangents)
9005         {
9006                 rsurface.modelvertex3f = (float *)vertex3f;
9007                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9008                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9009                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9010         }
9011         else if (wantnormals)
9012         {
9013                 rsurface.modelvertex3f = (float *)vertex3f;
9014                 rsurface.modelsvector3f = NULL;
9015                 rsurface.modeltvector3f = NULL;
9016                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9017         }
9018         else
9019         {
9020                 rsurface.modelvertex3f = (float *)vertex3f;
9021                 rsurface.modelsvector3f = NULL;
9022                 rsurface.modeltvector3f = NULL;
9023                 rsurface.modelnormal3f = NULL;
9024         }
9025         rsurface.modelvertexmesh = NULL;
9026         rsurface.modelvertexmesh_vertexbuffer = NULL;
9027         rsurface.modelvertexmesh_bufferoffset = 0;
9028         rsurface.modelvertex3f_vertexbuffer = 0;
9029         rsurface.modelvertex3f_bufferoffset = 0;
9030         rsurface.modelsvector3f_vertexbuffer = 0;
9031         rsurface.modelsvector3f_bufferoffset = 0;
9032         rsurface.modeltvector3f_vertexbuffer = 0;
9033         rsurface.modeltvector3f_bufferoffset = 0;
9034         rsurface.modelnormal3f_vertexbuffer = 0;
9035         rsurface.modelnormal3f_bufferoffset = 0;
9036         rsurface.modelgeneratedvertex = true;
9037         rsurface.modellightmapcolor4f  = (float *)color4f;
9038         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9039         rsurface.modellightmapcolor4f_bufferoffset = 0;
9040         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9041         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9042         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9043         rsurface.modeltexcoordlightmap2f  = NULL;
9044         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9045         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9046         rsurface.modelskeletalindex4ub = NULL;
9047         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9048         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9049         rsurface.modelskeletalweight4ub = NULL;
9050         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9051         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9052         rsurface.modelelement3i = (int *)element3i;
9053         rsurface.modelelement3i_indexbuffer = NULL;
9054         rsurface.modelelement3i_bufferoffset = 0;
9055         rsurface.modelelement3s = (unsigned short *)element3s;
9056         rsurface.modelelement3s_indexbuffer = NULL;
9057         rsurface.modelelement3s_bufferoffset = 0;
9058         rsurface.modellightmapoffsets = NULL;
9059         rsurface.modelsurfaces = NULL;
9060         rsurface.batchgeneratedvertex = false;
9061         rsurface.batchfirstvertex = 0;
9062         rsurface.batchnumvertices = 0;
9063         rsurface.batchfirsttriangle = 0;
9064         rsurface.batchnumtriangles = 0;
9065         rsurface.batchvertex3f  = NULL;
9066         rsurface.batchvertex3f_vertexbuffer = NULL;
9067         rsurface.batchvertex3f_bufferoffset = 0;
9068         rsurface.batchsvector3f = NULL;
9069         rsurface.batchsvector3f_vertexbuffer = NULL;
9070         rsurface.batchsvector3f_bufferoffset = 0;
9071         rsurface.batchtvector3f = NULL;
9072         rsurface.batchtvector3f_vertexbuffer = NULL;
9073         rsurface.batchtvector3f_bufferoffset = 0;
9074         rsurface.batchnormal3f  = NULL;
9075         rsurface.batchnormal3f_vertexbuffer = NULL;
9076         rsurface.batchnormal3f_bufferoffset = 0;
9077         rsurface.batchlightmapcolor4f = NULL;
9078         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9079         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9080         rsurface.batchtexcoordtexture2f = NULL;
9081         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9082         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9083         rsurface.batchtexcoordlightmap2f = NULL;
9084         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9085         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9086         rsurface.batchskeletalindex4ub = NULL;
9087         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9088         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9089         rsurface.batchskeletalweight4ub = NULL;
9090         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9091         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9092         rsurface.batchvertexmesh = NULL;
9093         rsurface.batchvertexmesh_vertexbuffer = NULL;
9094         rsurface.batchvertexmesh_bufferoffset = 0;
9095         rsurface.batchelement3i = NULL;
9096         rsurface.batchelement3i_indexbuffer = NULL;
9097         rsurface.batchelement3i_bufferoffset = 0;
9098         rsurface.batchelement3s = NULL;
9099         rsurface.batchelement3s_indexbuffer = NULL;
9100         rsurface.batchelement3s_bufferoffset = 0;
9101         rsurface.passcolor4f = NULL;
9102         rsurface.passcolor4f_vertexbuffer = NULL;
9103         rsurface.passcolor4f_bufferoffset = 0;
9104         rsurface.forcecurrenttextureupdate = true;
9105
9106         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9107         {
9108                 if ((wantnormals || wanttangents) && !normal3f)
9109                 {
9110                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9111                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9112                 }
9113                 if (wanttangents && !svector3f)
9114                 {
9115                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9116                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9117                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9118                 }
9119         }
9120 }
9121
9122 float RSurf_FogPoint(const float *v)
9123 {
9124         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9125         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9126         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9127         float FogHeightFade = r_refdef.fogheightfade;
9128         float fogfrac;
9129         unsigned int fogmasktableindex;
9130         if (r_refdef.fogplaneviewabove)
9131                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9132         else
9133                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9134         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9135         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9136 }
9137
9138 float RSurf_FogVertex(const float *v)
9139 {
9140         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9141         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9142         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9143         float FogHeightFade = rsurface.fogheightfade;
9144         float fogfrac;
9145         unsigned int fogmasktableindex;
9146         if (r_refdef.fogplaneviewabove)
9147                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9148         else
9149                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9150         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9151         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9152 }
9153
9154 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9155 {
9156         int i;
9157         for (i = 0;i < numelements;i++)
9158                 outelement3i[i] = inelement3i[i] + adjust;
9159 }
9160
9161 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9162 extern cvar_t gl_vbo;
9163 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9164 {
9165         int deformindex;
9166         int firsttriangle;
9167         int numtriangles;
9168         int firstvertex;
9169         int endvertex;
9170         int numvertices;
9171         int surfacefirsttriangle;
9172         int surfacenumtriangles;
9173         int surfacefirstvertex;
9174         int surfaceendvertex;
9175         int surfacenumvertices;
9176         int batchnumsurfaces = texturenumsurfaces;
9177         int batchnumvertices;
9178         int batchnumtriangles;
9179         int needsupdate;
9180         int i, j;
9181         qboolean gaps;
9182         qboolean dynamicvertex;
9183         float amplitude;
9184         float animpos;
9185         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9186         float waveparms[4];
9187         unsigned char *ub;
9188         q3shaderinfo_deform_t *deform;
9189         const msurface_t *surface, *firstsurface;
9190         r_vertexmesh_t *vertexmesh;
9191         if (!texturenumsurfaces)
9192                 return;
9193         // find vertex range of this surface batch
9194         gaps = false;
9195         firstsurface = texturesurfacelist[0];
9196         firsttriangle = firstsurface->num_firsttriangle;
9197         batchnumvertices = 0;
9198         batchnumtriangles = 0;
9199         firstvertex = endvertex = firstsurface->num_firstvertex;
9200         for (i = 0;i < texturenumsurfaces;i++)
9201         {
9202                 surface = texturesurfacelist[i];
9203                 if (surface != firstsurface + i)
9204                         gaps = true;
9205                 surfacefirstvertex = surface->num_firstvertex;
9206                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9207                 surfacenumvertices = surface->num_vertices;
9208                 surfacenumtriangles = surface->num_triangles;
9209                 if (firstvertex > surfacefirstvertex)
9210                         firstvertex = surfacefirstvertex;
9211                 if (endvertex < surfaceendvertex)
9212                         endvertex = surfaceendvertex;
9213                 batchnumvertices += surfacenumvertices;
9214                 batchnumtriangles += surfacenumtriangles;
9215         }
9216
9217         r_refdef.stats[r_stat_batch_batches]++;
9218         if (gaps)
9219                 r_refdef.stats[r_stat_batch_withgaps]++;
9220         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9221         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9222         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9223
9224         // we now know the vertex range used, and if there are any gaps in it
9225         rsurface.batchfirstvertex = firstvertex;
9226         rsurface.batchnumvertices = endvertex - firstvertex;
9227         rsurface.batchfirsttriangle = firsttriangle;
9228         rsurface.batchnumtriangles = batchnumtriangles;
9229
9230         // this variable holds flags for which properties have been updated that
9231         // may require regenerating vertexmesh array...
9232         needsupdate = 0;
9233
9234         // check if any dynamic vertex processing must occur
9235         dynamicvertex = false;
9236
9237         // a cvar to force the dynamic vertex path to be taken, for debugging
9238         if (r_batch_debugdynamicvertexpath.integer)
9239         {
9240                 if (!dynamicvertex)
9241                 {
9242                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9243                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9244                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9245                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9246                 }
9247                 dynamicvertex = true;
9248         }
9249
9250         // if there is a chance of animated vertex colors, it's a dynamic batch
9251         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9252         {
9253                 if (!dynamicvertex)
9254                 {
9255                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9256                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9257                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9258                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9259                 }
9260                 dynamicvertex = true;
9261                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9262         }
9263
9264         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9265         {
9266                 switch (deform->deform)
9267                 {
9268                 default:
9269                 case Q3DEFORM_PROJECTIONSHADOW:
9270                 case Q3DEFORM_TEXT0:
9271                 case Q3DEFORM_TEXT1:
9272                 case Q3DEFORM_TEXT2:
9273                 case Q3DEFORM_TEXT3:
9274                 case Q3DEFORM_TEXT4:
9275                 case Q3DEFORM_TEXT5:
9276                 case Q3DEFORM_TEXT6:
9277                 case Q3DEFORM_TEXT7:
9278                 case Q3DEFORM_NONE:
9279                         break;
9280                 case Q3DEFORM_AUTOSPRITE:
9281                         if (!dynamicvertex)
9282                         {
9283                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9284                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9285                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9286                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9287                         }
9288                         dynamicvertex = true;
9289                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9290                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9291                         break;
9292                 case Q3DEFORM_AUTOSPRITE2:
9293                         if (!dynamicvertex)
9294                         {
9295                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9296                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9297                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9298                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9299                         }
9300                         dynamicvertex = true;
9301                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9302                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9303                         break;
9304                 case Q3DEFORM_NORMAL:
9305                         if (!dynamicvertex)
9306                         {
9307                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9308                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9309                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9310                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9311                         }
9312                         dynamicvertex = true;
9313                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9314                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9315                         break;
9316                 case Q3DEFORM_WAVE:
9317                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9318                                 break; // if wavefunc is a nop, ignore this transform
9319                         if (!dynamicvertex)
9320                         {
9321                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9322                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9323                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9324                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9325                         }
9326                         dynamicvertex = true;
9327                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9328                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9329                         break;
9330                 case Q3DEFORM_BULGE:
9331                         if (!dynamicvertex)
9332                         {
9333                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9334                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9335                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9336                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9337                         }
9338                         dynamicvertex = true;
9339                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9340                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9341                         break;
9342                 case Q3DEFORM_MOVE:
9343                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9344                                 break; // if wavefunc is a nop, ignore this transform
9345                         if (!dynamicvertex)
9346                         {
9347                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9348                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9349                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9350                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9351                         }
9352                         dynamicvertex = true;
9353                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9354                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9355                         break;
9356                 }
9357         }
9358         if (rsurface.texture->materialshaderpass)
9359         {
9360                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9361                 {
9362                 default:
9363                 case Q3TCGEN_TEXTURE:
9364                         break;
9365                 case Q3TCGEN_LIGHTMAP:
9366                         if (!dynamicvertex)
9367                         {
9368                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9369                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9370                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9371                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9372                         }
9373                         dynamicvertex = true;
9374                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9375                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9376                         break;
9377                 case Q3TCGEN_VECTOR:
9378                         if (!dynamicvertex)
9379                         {
9380                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9381                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9382                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9383                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9384                         }
9385                         dynamicvertex = true;
9386                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9387                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9388                         break;
9389                 case Q3TCGEN_ENVIRONMENT:
9390                         if (!dynamicvertex)
9391                         {
9392                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9393                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9394                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9395                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9396                         }
9397                         dynamicvertex = true;
9398                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9399                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9400                         break;
9401                 }
9402                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9403                 {
9404                         if (!dynamicvertex)
9405                         {
9406                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9407                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9408                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9409                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9410                         }
9411                         dynamicvertex = true;
9412                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9413                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9414                 }
9415         }
9416
9417         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9418         {
9419                 if (!dynamicvertex)
9420                 {
9421                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9422                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9423                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9424                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9425                 }
9426                 dynamicvertex = true;
9427                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9428         }
9429
9430         // when the model data has no vertex buffer (dynamic mesh), we need to
9431         // eliminate gaps
9432         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9433                 batchneed |= BATCHNEED_NOGAPS;
9434
9435         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9436         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9437         // we ensure this by treating the vertex batch as dynamic...
9438         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9439         {
9440                 if (!dynamicvertex)
9441                 {
9442                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9443                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9444                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9445                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9446                 }
9447                 dynamicvertex = true;
9448         }
9449
9450         if (dynamicvertex)
9451         {
9452                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9453                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9454                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9455                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9456                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9457                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9458                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9459                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9460         }
9461
9462         // if needsupdate, we have to do a dynamic vertex batch for sure
9463         if (needsupdate & batchneed)
9464         {
9465                 if (!dynamicvertex)
9466                 {
9467                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9468                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9469                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9470                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9471                 }
9472                 dynamicvertex = true;
9473         }
9474
9475         // see if we need to build vertexmesh from arrays
9476         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9477         {
9478                 if (!dynamicvertex)
9479                 {
9480                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9481                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9482                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9483                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9484                 }
9485                 dynamicvertex = true;
9486         }
9487
9488         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9489         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9490                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9491
9492         rsurface.batchvertex3f = rsurface.modelvertex3f;
9493         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9494         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9495         rsurface.batchsvector3f = rsurface.modelsvector3f;
9496         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9497         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9498         rsurface.batchtvector3f = rsurface.modeltvector3f;
9499         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9500         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9501         rsurface.batchnormal3f = rsurface.modelnormal3f;
9502         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9503         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9504         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9505         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9506         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9507         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9508         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9509         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9510         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9511         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9512         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9513         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9514         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9515         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9516         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9517         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9518         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9519         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9520         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9521         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9522         rsurface.batchelement3i = rsurface.modelelement3i;
9523         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9524         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9525         rsurface.batchelement3s = rsurface.modelelement3s;
9526         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9527         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9528         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9529         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9530         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9531         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9532         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9533
9534         // if any dynamic vertex processing has to occur in software, we copy the
9535         // entire surface list together before processing to rebase the vertices
9536         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9537         //
9538         // if any gaps exist and we do not have a static vertex buffer, we have to
9539         // copy the surface list together to avoid wasting upload bandwidth on the
9540         // vertices in the gaps.
9541         //
9542         // if gaps exist and we have a static vertex buffer, we can choose whether
9543         // to combine the index buffer ranges into one dynamic index buffer or
9544         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9545         //
9546         // in many cases the batch is reduced to one draw call.
9547
9548         rsurface.batchmultidraw = false;
9549         rsurface.batchmultidrawnumsurfaces = 0;
9550         rsurface.batchmultidrawsurfacelist = NULL;
9551
9552         if (!dynamicvertex)
9553         {
9554                 // static vertex data, just set pointers...
9555                 rsurface.batchgeneratedvertex = false;
9556                 // if there are gaps, we want to build a combined index buffer,
9557                 // otherwise use the original static buffer with an appropriate offset
9558                 if (gaps)
9559                 {
9560                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9561                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9562                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9563                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9564                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9565                         {
9566                                 rsurface.batchmultidraw = true;
9567                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9568                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9569                                 return;
9570                         }
9571                         // build a new triangle elements array for this batch
9572                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9573                         rsurface.batchfirsttriangle = 0;
9574                         numtriangles = 0;
9575                         for (i = 0;i < texturenumsurfaces;i++)
9576                         {
9577                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9578                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9579                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9580                                 numtriangles += surfacenumtriangles;
9581                         }
9582                         rsurface.batchelement3i_indexbuffer = NULL;
9583                         rsurface.batchelement3i_bufferoffset = 0;
9584                         rsurface.batchelement3s = NULL;
9585                         rsurface.batchelement3s_indexbuffer = NULL;
9586                         rsurface.batchelement3s_bufferoffset = 0;
9587                         if (endvertex <= 65536)
9588                         {
9589                                 // make a 16bit (unsigned short) index array if possible
9590                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9591                                 for (i = 0;i < numtriangles*3;i++)
9592                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9593                         }
9594                         // upload buffer data for the copytriangles batch
9595                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9596                         {
9597                                 if (rsurface.batchelement3s)
9598                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9599                                 else if (rsurface.batchelement3i)
9600                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9601                         }
9602                 }
9603                 else
9604                 {
9605                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9606                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9607                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9608                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9609                 }
9610                 return;
9611         }
9612
9613         // something needs software processing, do it for real...
9614         // we only directly handle separate array data in this case and then
9615         // generate interleaved data if needed...
9616         rsurface.batchgeneratedvertex = true;
9617         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9618         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9619         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9620         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9621
9622         // now copy the vertex data into a combined array and make an index array
9623         // (this is what Quake3 does all the time)
9624         // we also apply any skeletal animation here that would have been done in
9625         // the vertex shader, because most of the dynamic vertex animation cases
9626         // need actual vertex positions and normals
9627         //if (dynamicvertex)
9628         {
9629                 rsurface.batchvertexmesh = NULL;
9630                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9631                 rsurface.batchvertexmesh_bufferoffset = 0;
9632                 rsurface.batchvertex3f = NULL;
9633                 rsurface.batchvertex3f_vertexbuffer = NULL;
9634                 rsurface.batchvertex3f_bufferoffset = 0;
9635                 rsurface.batchsvector3f = NULL;
9636                 rsurface.batchsvector3f_vertexbuffer = NULL;
9637                 rsurface.batchsvector3f_bufferoffset = 0;
9638                 rsurface.batchtvector3f = NULL;
9639                 rsurface.batchtvector3f_vertexbuffer = NULL;
9640                 rsurface.batchtvector3f_bufferoffset = 0;
9641                 rsurface.batchnormal3f = NULL;
9642                 rsurface.batchnormal3f_vertexbuffer = NULL;
9643                 rsurface.batchnormal3f_bufferoffset = 0;
9644                 rsurface.batchlightmapcolor4f = NULL;
9645                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9646                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9647                 rsurface.batchtexcoordtexture2f = NULL;
9648                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9649                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9650                 rsurface.batchtexcoordlightmap2f = NULL;
9651                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9652                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9653                 rsurface.batchskeletalindex4ub = NULL;
9654                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9655                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9656                 rsurface.batchskeletalweight4ub = NULL;
9657                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9658                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9659                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9660                 rsurface.batchelement3i_indexbuffer = NULL;
9661                 rsurface.batchelement3i_bufferoffset = 0;
9662                 rsurface.batchelement3s = NULL;
9663                 rsurface.batchelement3s_indexbuffer = NULL;
9664                 rsurface.batchelement3s_bufferoffset = 0;
9665                 rsurface.batchskeletaltransform3x4buffer = NULL;
9666                 rsurface.batchskeletaltransform3x4offset = 0;
9667                 rsurface.batchskeletaltransform3x4size = 0;
9668                 // we'll only be setting up certain arrays as needed
9669                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9670                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9671                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9672                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9673                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9674                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9675                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9676                 {
9677                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9678                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9679                 }
9680                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9681                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9682                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9683                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9684                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9685                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9686                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9687                 {
9688                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9689                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9690                 }
9691                 numvertices = 0;
9692                 numtriangles = 0;
9693                 for (i = 0;i < texturenumsurfaces;i++)
9694                 {
9695                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9696                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9697                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9698                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9699                         // copy only the data requested
9700                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9701                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9702                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9703                         {
9704                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9705                                 {
9706                                         if (rsurface.batchvertex3f)
9707                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9708                                         else
9709                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9710                                 }
9711                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9712                                 {
9713                                         if (rsurface.modelnormal3f)
9714                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9715                                         else
9716                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9717                                 }
9718                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9719                                 {
9720                                         if (rsurface.modelsvector3f)
9721                                         {
9722                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9723                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9724                                         }
9725                                         else
9726                                         {
9727                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9728                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9729                                         }
9730                                 }
9731                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9732                                 {
9733                                         if (rsurface.modellightmapcolor4f)
9734                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9735                                         else
9736                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9737                                 }
9738                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9739                                 {
9740                                         if (rsurface.modeltexcoordtexture2f)
9741                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9742                                         else
9743                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9744                                 }
9745                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9746                                 {
9747                                         if (rsurface.modeltexcoordlightmap2f)
9748                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9749                                         else
9750                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9751                                 }
9752                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9753                                 {
9754                                         if (rsurface.modelskeletalindex4ub)
9755                                         {
9756                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9757                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9758                                         }
9759                                         else
9760                                         {
9761                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9762                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9763                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9764                                                 for (j = 0;j < surfacenumvertices;j++)
9765                                                         ub[j*4] = 255;
9766                                         }
9767                                 }
9768                         }
9769                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9770                         numvertices += surfacenumvertices;
9771                         numtriangles += surfacenumtriangles;
9772                 }
9773
9774                 // generate a 16bit index array as well if possible
9775                 // (in general, dynamic batches fit)
9776                 if (numvertices <= 65536)
9777                 {
9778                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9779                         for (i = 0;i < numtriangles*3;i++)
9780                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9781                 }
9782
9783                 // since we've copied everything, the batch now starts at 0
9784                 rsurface.batchfirstvertex = 0;
9785                 rsurface.batchnumvertices = batchnumvertices;
9786                 rsurface.batchfirsttriangle = 0;
9787                 rsurface.batchnumtriangles = batchnumtriangles;
9788         }
9789
9790         // apply skeletal animation that would have been done in the vertex shader
9791         if (rsurface.batchskeletaltransform3x4)
9792         {
9793                 const unsigned char *si;
9794                 const unsigned char *sw;
9795                 const float *t[4];
9796                 const float *b = rsurface.batchskeletaltransform3x4;
9797                 float *vp, *vs, *vt, *vn;
9798                 float w[4];
9799                 float m[3][4], n[3][4];
9800                 float tp[3], ts[3], tt[3], tn[3];
9801                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9802                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9803                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9804                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9805                 si = rsurface.batchskeletalindex4ub;
9806                 sw = rsurface.batchskeletalweight4ub;
9807                 vp = rsurface.batchvertex3f;
9808                 vs = rsurface.batchsvector3f;
9809                 vt = rsurface.batchtvector3f;
9810                 vn = rsurface.batchnormal3f;
9811                 memset(m[0], 0, sizeof(m));
9812                 memset(n[0], 0, sizeof(n));
9813                 for (i = 0;i < batchnumvertices;i++)
9814                 {
9815                         t[0] = b + si[0]*12;
9816                         if (sw[0] == 255)
9817                         {
9818                                 // common case - only one matrix
9819                                 m[0][0] = t[0][ 0];
9820                                 m[0][1] = t[0][ 1];
9821                                 m[0][2] = t[0][ 2];
9822                                 m[0][3] = t[0][ 3];
9823                                 m[1][0] = t[0][ 4];
9824                                 m[1][1] = t[0][ 5];
9825                                 m[1][2] = t[0][ 6];
9826                                 m[1][3] = t[0][ 7];
9827                                 m[2][0] = t[0][ 8];
9828                                 m[2][1] = t[0][ 9];
9829                                 m[2][2] = t[0][10];
9830                                 m[2][3] = t[0][11];
9831                         }
9832                         else if (sw[2] + sw[3])
9833                         {
9834                                 // blend 4 matrices
9835                                 t[1] = b + si[1]*12;
9836                                 t[2] = b + si[2]*12;
9837                                 t[3] = b + si[3]*12;
9838                                 w[0] = sw[0] * (1.0f / 255.0f);
9839                                 w[1] = sw[1] * (1.0f / 255.0f);
9840                                 w[2] = sw[2] * (1.0f / 255.0f);
9841                                 w[3] = sw[3] * (1.0f / 255.0f);
9842                                 // blend the matrices
9843                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9844                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9845                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9846                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9847                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9848                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9849                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9850                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9851                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9852                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9853                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9854                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9855                         }
9856                         else
9857                         {
9858                                 // blend 2 matrices
9859                                 t[1] = b + si[1]*12;
9860                                 w[0] = sw[0] * (1.0f / 255.0f);
9861                                 w[1] = sw[1] * (1.0f / 255.0f);
9862                                 // blend the matrices
9863                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9864                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9865                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9866                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9867                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9868                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9869                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9870                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9871                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9872                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9873                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9874                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9875                         }
9876                         si += 4;
9877                         sw += 4;
9878                         // modify the vertex
9879                         VectorCopy(vp, tp);
9880                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9881                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9882                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9883                         vp += 3;
9884                         if (vn)
9885                         {
9886                                 // the normal transformation matrix is a set of cross products...
9887                                 CrossProduct(m[1], m[2], n[0]);
9888                                 CrossProduct(m[2], m[0], n[1]);
9889                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9890                                 VectorCopy(vn, tn);
9891                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9892                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9893                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9894                                 VectorNormalize(vn);
9895                                 vn += 3;
9896                                 if (vs)
9897                                 {
9898                                         VectorCopy(vs, ts);
9899                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9900                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9901                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9902                                         VectorNormalize(vs);
9903                                         vs += 3;
9904                                         VectorCopy(vt, tt);
9905                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9906                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9907                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9908                                         VectorNormalize(vt);
9909                                         vt += 3;
9910                                 }
9911                         }
9912                 }
9913                 rsurface.batchskeletaltransform3x4 = NULL;
9914                 rsurface.batchskeletalnumtransforms = 0;
9915         }
9916
9917         // q1bsp surfaces rendered in vertex color mode have to have colors
9918         // calculated based on lightstyles
9919         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9920         {
9921                 // generate color arrays for the surfaces in this list
9922                 int c[4];
9923                 int scale;
9924                 int size3;
9925                 const int *offsets;
9926                 const unsigned char *lm;
9927                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9928                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9929                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9930                 numvertices = 0;
9931                 for (i = 0;i < texturenumsurfaces;i++)
9932                 {
9933                         surface = texturesurfacelist[i];
9934                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9935                         surfacenumvertices = surface->num_vertices;
9936                         if (surface->lightmapinfo->samples)
9937                         {
9938                                 for (j = 0;j < surfacenumvertices;j++)
9939                                 {
9940                                         lm = surface->lightmapinfo->samples + offsets[j];
9941                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9942                                         VectorScale(lm, scale, c);
9943                                         if (surface->lightmapinfo->styles[1] != 255)
9944                                         {
9945                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9946                                                 lm += size3;
9947                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9948                                                 VectorMA(c, scale, lm, c);
9949                                                 if (surface->lightmapinfo->styles[2] != 255)
9950                                                 {
9951                                                         lm += size3;
9952                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9953                                                         VectorMA(c, scale, lm, c);
9954                                                         if (surface->lightmapinfo->styles[3] != 255)
9955                                                         {
9956                                                                 lm += size3;
9957                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9958                                                                 VectorMA(c, scale, lm, c);
9959                                                         }
9960                                                 }
9961                                         }
9962                                         c[0] >>= 7;
9963                                         c[1] >>= 7;
9964                                         c[2] >>= 7;
9965                                         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);
9966                                         numvertices++;
9967                                 }
9968                         }
9969                         else
9970                         {
9971                                 for (j = 0;j < surfacenumvertices;j++)
9972                                 {
9973                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9974                                         numvertices++;
9975                                 }
9976                         }
9977                 }
9978         }
9979
9980         // if vertices are deformed (sprite flares and things in maps, possibly
9981         // water waves, bulges and other deformations), modify the copied vertices
9982         // in place
9983         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9984         {
9985                 float scale;
9986                 switch (deform->deform)
9987                 {
9988                 default:
9989                 case Q3DEFORM_PROJECTIONSHADOW:
9990                 case Q3DEFORM_TEXT0:
9991                 case Q3DEFORM_TEXT1:
9992                 case Q3DEFORM_TEXT2:
9993                 case Q3DEFORM_TEXT3:
9994                 case Q3DEFORM_TEXT4:
9995                 case Q3DEFORM_TEXT5:
9996                 case Q3DEFORM_TEXT6:
9997                 case Q3DEFORM_TEXT7:
9998                 case Q3DEFORM_NONE:
9999                         break;
10000                 case Q3DEFORM_AUTOSPRITE:
10001                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10002                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10003                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10004                         VectorNormalize(newforward);
10005                         VectorNormalize(newright);
10006                         VectorNormalize(newup);
10007 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10008 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10009 //                      rsurface.batchvertex3f_bufferoffset = 0;
10010 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10011 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
10012 //                      rsurface.batchsvector3f_bufferoffset = 0;
10013 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10014 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
10015 //                      rsurface.batchtvector3f_bufferoffset = 0;
10016 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10017 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10018 //                      rsurface.batchnormal3f_bufferoffset = 0;
10019                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10020                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10021                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10022                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10023                                 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);
10024                         // a single autosprite surface can contain multiple sprites...
10025                         for (j = 0;j < batchnumvertices - 3;j += 4)
10026                         {
10027                                 VectorClear(center);
10028                                 for (i = 0;i < 4;i++)
10029                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10030                                 VectorScale(center, 0.25f, center);
10031                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10032                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10033                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10034                                 for (i = 0;i < 4;i++)
10035                                 {
10036                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10037                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10038                                 }
10039                         }
10040                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10041                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10042                         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);
10043                         break;
10044                 case Q3DEFORM_AUTOSPRITE2:
10045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10046                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10048                         VectorNormalize(newforward);
10049                         VectorNormalize(newright);
10050                         VectorNormalize(newup);
10051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10053 //                      rsurface.batchvertex3f_bufferoffset = 0;
10054                         {
10055                                 const float *v1, *v2;
10056                                 vec3_t start, end;
10057                                 float f, l;
10058                                 struct
10059                                 {
10060                                         float length2;
10061                                         const float *v1;
10062                                         const float *v2;
10063                                 }
10064                                 shortest[2];
10065                                 memset(shortest, 0, sizeof(shortest));
10066                                 // a single autosprite surface can contain multiple sprites...
10067                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10068                                 {
10069                                         VectorClear(center);
10070                                         for (i = 0;i < 4;i++)
10071                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10072                                         VectorScale(center, 0.25f, center);
10073                                         // find the two shortest edges, then use them to define the
10074                                         // axis vectors for rotating around the central axis
10075                                         for (i = 0;i < 6;i++)
10076                                         {
10077                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10078                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10079                                                 l = VectorDistance2(v1, v2);
10080                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10081                                                 if (v1[2] != v2[2])
10082                                                         l += (1.0f / 1024.0f);
10083                                                 if (shortest[0].length2 > l || i == 0)
10084                                                 {
10085                                                         shortest[1] = shortest[0];
10086                                                         shortest[0].length2 = l;
10087                                                         shortest[0].v1 = v1;
10088                                                         shortest[0].v2 = v2;
10089                                                 }
10090                                                 else if (shortest[1].length2 > l || i == 1)
10091                                                 {
10092                                                         shortest[1].length2 = l;
10093                                                         shortest[1].v1 = v1;
10094                                                         shortest[1].v2 = v2;
10095                                                 }
10096                                         }
10097                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10098                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10099                                         // this calculates the right vector from the shortest edge
10100                                         // and the up vector from the edge midpoints
10101                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10102                                         VectorNormalize(right);
10103                                         VectorSubtract(end, start, up);
10104                                         VectorNormalize(up);
10105                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10106                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10107                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10108                                         VectorNegate(forward, forward);
10109                                         VectorReflect(forward, 0, up, forward);
10110                                         VectorNormalize(forward);
10111                                         CrossProduct(up, forward, newright);
10112                                         VectorNormalize(newright);
10113                                         // rotate the quad around the up axis vector, this is made
10114                                         // especially easy by the fact we know the quad is flat,
10115                                         // so we only have to subtract the center position and
10116                                         // measure distance along the right vector, and then
10117                                         // multiply that by the newright vector and add back the
10118                                         // center position
10119                                         // we also need to subtract the old position to undo the
10120                                         // displacement from the center, which we do with a
10121                                         // DotProduct, the subtraction/addition of center is also
10122                                         // optimized into DotProducts here
10123                                         l = DotProduct(right, center);
10124                                         for (i = 0;i < 4;i++)
10125                                         {
10126                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10127                                                 f = DotProduct(right, v1) - l;
10128                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10129                                         }
10130                                 }
10131                         }
10132                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10133                         {
10134 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10135 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10136 //                              rsurface.batchnormal3f_bufferoffset = 0;
10137                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10138                         }
10139                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10140                         {
10141 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10142 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10143 //                              rsurface.batchsvector3f_bufferoffset = 0;
10144 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10145 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10146 //                              rsurface.batchtvector3f_bufferoffset = 0;
10147                                 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);
10148                         }
10149                         break;
10150                 case Q3DEFORM_NORMAL:
10151                         // deform the normals to make reflections wavey
10152                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10153                         rsurface.batchnormal3f_vertexbuffer = NULL;
10154                         rsurface.batchnormal3f_bufferoffset = 0;
10155                         for (j = 0;j < batchnumvertices;j++)
10156                         {
10157                                 float vertex[3];
10158                                 float *normal = rsurface.batchnormal3f + 3*j;
10159                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10160                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10161                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10162                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10163                                 VectorNormalize(normal);
10164                         }
10165                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10166                         {
10167 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10168 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10169 //                              rsurface.batchsvector3f_bufferoffset = 0;
10170 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10171 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10172 //                              rsurface.batchtvector3f_bufferoffset = 0;
10173                                 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);
10174                         }
10175                         break;
10176                 case Q3DEFORM_WAVE:
10177                         // deform vertex array to make wavey water and flags and such
10178                         waveparms[0] = deform->waveparms[0];
10179                         waveparms[1] = deform->waveparms[1];
10180                         waveparms[2] = deform->waveparms[2];
10181                         waveparms[3] = deform->waveparms[3];
10182                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10183                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10184                         // this is how a divisor of vertex influence on deformation
10185                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10186                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10187 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10188 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10189 //                      rsurface.batchvertex3f_bufferoffset = 0;
10190 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10191 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10192 //                      rsurface.batchnormal3f_bufferoffset = 0;
10193                         for (j = 0;j < batchnumvertices;j++)
10194                         {
10195                                 // if the wavefunc depends on time, evaluate it per-vertex
10196                                 if (waveparms[3])
10197                                 {
10198                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10199                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10200                                 }
10201                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10202                         }
10203                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10204                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10205                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10206                         {
10207 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10208 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10209 //                              rsurface.batchsvector3f_bufferoffset = 0;
10210 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10211 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10212 //                              rsurface.batchtvector3f_bufferoffset = 0;
10213                                 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);
10214                         }
10215                         break;
10216                 case Q3DEFORM_BULGE:
10217                         // deform vertex array to make the surface have moving bulges
10218 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10219 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10220 //                      rsurface.batchvertex3f_bufferoffset = 0;
10221 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10222 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10223 //                      rsurface.batchnormal3f_bufferoffset = 0;
10224                         for (j = 0;j < batchnumvertices;j++)
10225                         {
10226                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10227                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10228                         }
10229                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10230                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10231                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10232                         {
10233 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10234 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10235 //                              rsurface.batchsvector3f_bufferoffset = 0;
10236 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10237 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10238 //                              rsurface.batchtvector3f_bufferoffset = 0;
10239                                 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);
10240                         }
10241                         break;
10242                 case Q3DEFORM_MOVE:
10243                         // deform vertex array
10244                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10245                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10246                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10247                         VectorScale(deform->parms, scale, waveparms);
10248 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10249 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10250 //                      rsurface.batchvertex3f_bufferoffset = 0;
10251                         for (j = 0;j < batchnumvertices;j++)
10252                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10253                         break;
10254                 }
10255         }
10256
10257         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10258         {
10259         // generate texcoords based on the chosen texcoord source
10260                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10261                 {
10262                 default:
10263                 case Q3TCGEN_TEXTURE:
10264                         break;
10265                 case Q3TCGEN_LIGHTMAP:
10266         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10267         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10268         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10269                         if (rsurface.batchtexcoordlightmap2f)
10270                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10271                         break;
10272                 case Q3TCGEN_VECTOR:
10273         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10274         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10275         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10276                         for (j = 0;j < batchnumvertices;j++)
10277                         {
10278                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10279                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10280                         }
10281                         break;
10282                 case Q3TCGEN_ENVIRONMENT:
10283                         // make environment reflections using a spheremap
10284                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10285                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10286                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10287                         for (j = 0;j < batchnumvertices;j++)
10288                         {
10289                                 // identical to Q3A's method, but executed in worldspace so
10290                                 // carried models can be shiny too
10291
10292                                 float viewer[3], d, reflected[3], worldreflected[3];
10293
10294                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10295                                 // VectorNormalize(viewer);
10296
10297                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10298
10299                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10300                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10301                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10302                                 // note: this is proportinal to viewer, so we can normalize later
10303
10304                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10305                                 VectorNormalize(worldreflected);
10306
10307                                 // note: this sphere map only uses world x and z!
10308                                 // so positive and negative y will LOOK THE SAME.
10309                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10310                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10311                         }
10312                         break;
10313                 }
10314                 // the only tcmod that needs software vertex processing is turbulent, so
10315                 // check for it here and apply the changes if needed
10316                 // and we only support that as the first one
10317                 // (handling a mixture of turbulent and other tcmods would be problematic
10318                 //  without punting it entirely to a software path)
10319                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10320                 {
10321                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10322                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10323         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10324         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10325         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10326                         for (j = 0;j < batchnumvertices;j++)
10327                         {
10328                                 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);
10329                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10330                         }
10331                 }
10332         }
10333
10334         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10335         {
10336                 // convert the modified arrays to vertex structs
10337 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10338 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10339 //              rsurface.batchvertexmesh_bufferoffset = 0;
10340                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10341                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10342                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10343                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10344                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10345                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10346                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10347                 {
10348                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10349                         {
10350                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10351                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10352                         }
10353                 }
10354                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10355                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10356                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10357                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10358                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10359                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10360                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10361                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10362                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10363                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10364                 {
10365                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10366                         {
10367                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10368                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10369                         }
10370                 }
10371         }
10372
10373         // upload buffer data for the dynamic batch
10374         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10375         {
10376                 if (rsurface.batchvertexmesh)
10377                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10378                 else
10379                 {
10380                         if (rsurface.batchvertex3f)
10381                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10382                         if (rsurface.batchsvector3f)
10383                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10384                         if (rsurface.batchtvector3f)
10385                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10386                         if (rsurface.batchnormal3f)
10387                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10388                         if (rsurface.batchlightmapcolor4f)
10389                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10390                         if (rsurface.batchtexcoordtexture2f)
10391                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10392                         if (rsurface.batchtexcoordlightmap2f)
10393                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10394                         if (rsurface.batchskeletalindex4ub)
10395                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10396                         if (rsurface.batchskeletalweight4ub)
10397                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10398                 }
10399                 if (rsurface.batchelement3s)
10400                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10401                 else if (rsurface.batchelement3i)
10402                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10403         }
10404 }
10405
10406 void RSurf_DrawBatch(void)
10407 {
10408         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10409         // through the pipeline, killing it earlier in the pipeline would have
10410         // per-surface overhead rather than per-batch overhead, so it's best to
10411         // reject it here, before it hits glDraw.
10412         if (rsurface.batchnumtriangles == 0)
10413                 return;
10414 #if 0
10415         // batch debugging code
10416         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10417         {
10418                 int i;
10419                 int j;
10420                 int c;
10421                 const int *e;
10422                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10423                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10424                 {
10425                         c = e[i];
10426                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10427                         {
10428                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10429                                 {
10430                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10431                                                 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);
10432                                         break;
10433                                 }
10434                         }
10435                 }
10436         }
10437 #endif
10438         if (rsurface.batchmultidraw)
10439         {
10440                 // issue multiple draws rather than copying index data
10441                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10442                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10443                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10444                 for (i = 0;i < numsurfaces;)
10445                 {
10446                         // combine consecutive surfaces as one draw
10447                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10448                                 if (surfacelist[j] != surfacelist[k] + 1)
10449                                         break;
10450                         firstvertex = surfacelist[i]->num_firstvertex;
10451                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10452                         firsttriangle = surfacelist[i]->num_firsttriangle;
10453                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10454                         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);
10455                         i = j;
10456                 }
10457         }
10458         else
10459         {
10460                 // there is only one consecutive run of index data (may have been combined)
10461                 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);
10462         }
10463 }
10464
10465 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10466 {
10467         // pick the closest matching water plane
10468         int planeindex, vertexindex, bestplaneindex = -1;
10469         float d, bestd;
10470         vec3_t vert;
10471         const float *v;
10472         r_waterstate_waterplane_t *p;
10473         qboolean prepared = false;
10474         bestd = 0;
10475         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10476         {
10477                 if(p->camera_entity != rsurface.texture->camera_entity)
10478                         continue;
10479                 d = 0;
10480                 if(!prepared)
10481                 {
10482                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10483                         prepared = true;
10484                         if(rsurface.batchnumvertices == 0)
10485                                 break;
10486                 }
10487                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10488                 {
10489                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10490                         d += fabs(PlaneDiff(vert, &p->plane));
10491                 }
10492                 if (bestd > d || bestplaneindex < 0)
10493                 {
10494                         bestd = d;
10495                         bestplaneindex = planeindex;
10496                 }
10497         }
10498         return bestplaneindex;
10499         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10500         // this situation though, as it might be better to render single larger
10501         // batches with useless stuff (backface culled for example) than to
10502         // render multiple smaller batches
10503 }
10504
10505 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10506 {
10507         int i;
10508         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10509         rsurface.passcolor4f_vertexbuffer = 0;
10510         rsurface.passcolor4f_bufferoffset = 0;
10511         for (i = 0;i < rsurface.batchnumvertices;i++)
10512                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10513 }
10514
10515 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10516 {
10517         int i;
10518         float f;
10519         const float *v;
10520         const float *c;
10521         float *c2;
10522         if (rsurface.passcolor4f)
10523         {
10524                 // generate color arrays
10525                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10526                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10527                 rsurface.passcolor4f_vertexbuffer = 0;
10528                 rsurface.passcolor4f_bufferoffset = 0;
10529                 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)
10530                 {
10531                         f = RSurf_FogVertex(v);
10532                         c2[0] = c[0] * f;
10533                         c2[1] = c[1] * f;
10534                         c2[2] = c[2] * f;
10535                         c2[3] = c[3];
10536                 }
10537         }
10538         else
10539         {
10540                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10541                 rsurface.passcolor4f_vertexbuffer = 0;
10542                 rsurface.passcolor4f_bufferoffset = 0;
10543                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10544                 {
10545                         f = RSurf_FogVertex(v);
10546                         c2[0] = f;
10547                         c2[1] = f;
10548                         c2[2] = f;
10549                         c2[3] = 1;
10550                 }
10551         }
10552 }
10553
10554 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10555 {
10556         int i;
10557         float f;
10558         const float *v;
10559         const float *c;
10560         float *c2;
10561         if (!rsurface.passcolor4f)
10562                 return;
10563         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10564         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10565         rsurface.passcolor4f_vertexbuffer = 0;
10566         rsurface.passcolor4f_bufferoffset = 0;
10567         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)
10568         {
10569                 f = RSurf_FogVertex(v);
10570                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10571                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10572                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10573                 c2[3] = c[3];
10574         }
10575 }
10576
10577 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10578 {
10579         int i;
10580         const float *c;
10581         float *c2;
10582         if (!rsurface.passcolor4f)
10583                 return;
10584         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10585         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10586         rsurface.passcolor4f_vertexbuffer = 0;
10587         rsurface.passcolor4f_bufferoffset = 0;
10588         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10589         {
10590                 c2[0] = c[0] * r;
10591                 c2[1] = c[1] * g;
10592                 c2[2] = c[2] * b;
10593                 c2[3] = c[3] * a;
10594         }
10595 }
10596
10597 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10598 {
10599         int i;
10600         const float *c;
10601         float *c2;
10602         if (!rsurface.passcolor4f)
10603                 return;
10604         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10605         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10606         rsurface.passcolor4f_vertexbuffer = 0;
10607         rsurface.passcolor4f_bufferoffset = 0;
10608         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10609         {
10610                 c2[0] = c[0] + r_refdef.scene.ambient;
10611                 c2[1] = c[1] + r_refdef.scene.ambient;
10612                 c2[2] = c[2] + r_refdef.scene.ambient;
10613                 c2[3] = c[3];
10614         }
10615 }
10616
10617 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10618 {
10619         // TODO: optimize
10620         rsurface.passcolor4f = NULL;
10621         rsurface.passcolor4f_vertexbuffer = 0;
10622         rsurface.passcolor4f_bufferoffset = 0;
10623         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10624         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10625         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10626         GL_Color(r, g, b, a);
10627         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10628         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10629         R_Mesh_TexMatrix(0, NULL);
10630         RSurf_DrawBatch();
10631 }
10632
10633 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10634 {
10635         // TODO: optimize applyfog && applycolor case
10636         // just apply fog if necessary, and tint the fog color array if necessary
10637         rsurface.passcolor4f = NULL;
10638         rsurface.passcolor4f_vertexbuffer = 0;
10639         rsurface.passcolor4f_bufferoffset = 0;
10640         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10641         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10642         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10643         GL_Color(r, g, b, a);
10644         RSurf_DrawBatch();
10645 }
10646
10647 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10648 {
10649         // TODO: optimize
10650         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10651         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10652         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10653         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10654         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10655         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10656         GL_Color(r, g, b, a);
10657         RSurf_DrawBatch();
10658 }
10659
10660 static void RSurf_DrawBatch_GL11_ClampColor(void)
10661 {
10662         int i;
10663         const float *c1;
10664         float *c2;
10665         if (!rsurface.passcolor4f)
10666                 return;
10667         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10668         {
10669                 c2[0] = bound(0.0f, c1[0], 1.0f);
10670                 c2[1] = bound(0.0f, c1[1], 1.0f);
10671                 c2[2] = bound(0.0f, c1[2], 1.0f);
10672                 c2[3] = bound(0.0f, c1[3], 1.0f);
10673         }
10674 }
10675
10676 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10677 {
10678         int i;
10679         float f;
10680         const float *v;
10681         const float *n;
10682         float *c;
10683         //vec3_t eyedir;
10684
10685         // fake shading
10686         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10687         rsurface.passcolor4f_vertexbuffer = 0;
10688         rsurface.passcolor4f_bufferoffset = 0;
10689         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)
10690         {
10691                 f = -DotProduct(r_refdef.view.forward, n);
10692                 f = max(0, f);
10693                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10694                 f *= r_refdef.lightmapintensity;
10695                 Vector4Set(c, f, f, f, 1);
10696         }
10697 }
10698
10699 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10700 {
10701         RSurf_DrawBatch_GL11_ApplyFakeLight();
10702         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10703         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10704         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10705         GL_Color(r, g, b, a);
10706         RSurf_DrawBatch();
10707 }
10708
10709 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10710 {
10711         int i;
10712         float f;
10713         float alpha;
10714         const float *v;
10715         const float *n;
10716         float *c;
10717         vec3_t ambientcolor;
10718         vec3_t diffusecolor;
10719         vec3_t lightdir;
10720         // TODO: optimize
10721         // model lighting
10722         VectorCopy(rsurface.modellight_lightdir, lightdir);
10723         f = 0.5f * r_refdef.lightmapintensity;
10724         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10725         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10726         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10727         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10728         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10729         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10730         alpha = *a;
10731         if (VectorLength2(diffusecolor) > 0)
10732         {
10733                 // q3-style directional shading
10734                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10735                 rsurface.passcolor4f_vertexbuffer = 0;
10736                 rsurface.passcolor4f_bufferoffset = 0;
10737                 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)
10738                 {
10739                         if ((f = DotProduct(n, lightdir)) > 0)
10740                                 VectorMA(ambientcolor, f, diffusecolor, c);
10741                         else
10742                                 VectorCopy(ambientcolor, c);
10743                         c[3] = alpha;
10744                 }
10745                 *r = 1;
10746                 *g = 1;
10747                 *b = 1;
10748                 *a = 1;
10749                 *applycolor = false;
10750         }
10751         else
10752         {
10753                 *r = ambientcolor[0];
10754                 *g = ambientcolor[1];
10755                 *b = ambientcolor[2];
10756                 rsurface.passcolor4f = NULL;
10757                 rsurface.passcolor4f_vertexbuffer = 0;
10758                 rsurface.passcolor4f_bufferoffset = 0;
10759         }
10760 }
10761
10762 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10763 {
10764         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10765         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10766         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10767         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10768         GL_Color(r, g, b, a);
10769         RSurf_DrawBatch();
10770 }
10771
10772 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10773 {
10774         int i;
10775         float f;
10776         const float *v;
10777         float *c;
10778
10779         // fake shading
10780         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10781         rsurface.passcolor4f_vertexbuffer = 0;
10782         rsurface.passcolor4f_bufferoffset = 0;
10783
10784         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10785         {
10786                 f = 1 - RSurf_FogVertex(v);
10787                 c[0] = r;
10788                 c[1] = g;
10789                 c[2] = b;
10790                 c[3] = f * a;
10791         }
10792 }
10793
10794 void RSurf_SetupDepthAndCulling(void)
10795 {
10796         // submodels are biased to avoid z-fighting with world surfaces that they
10797         // may be exactly overlapping (avoids z-fighting artifacts on certain
10798         // doors and things in Quake maps)
10799         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10800         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10801         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10802         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10803 }
10804
10805 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10806 {
10807         // transparent sky would be ridiculous
10808         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10809                 return;
10810         R_SetupShader_Generic_NoTexture(false, false);
10811         skyrenderlater = true;
10812         RSurf_SetupDepthAndCulling();
10813         GL_DepthMask(true);
10814         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10815         // skymasking on them, and Quake3 never did sky masking (unlike
10816         // software Quake and software Quake2), so disable the sky masking
10817         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10818         // and skymasking also looks very bad when noclipping outside the
10819         // level, so don't use it then either.
10820         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10821         {
10822                 R_Mesh_ResetTextureState();
10823                 if (skyrendermasked)
10824                 {
10825                         R_SetupShader_DepthOrShadow(false, false, false);
10826                         // depth-only (masking)
10827                         GL_ColorMask(0,0,0,0);
10828                         // just to make sure that braindead drivers don't draw
10829                         // anything despite that colormask...
10830                         GL_BlendFunc(GL_ZERO, GL_ONE);
10831                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10832                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10833                 }
10834                 else
10835                 {
10836                         R_SetupShader_Generic_NoTexture(false, false);
10837                         // fog sky
10838                         GL_BlendFunc(GL_ONE, GL_ZERO);
10839                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10840                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10841                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10842                 }
10843                 RSurf_DrawBatch();
10844                 if (skyrendermasked)
10845                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10846         }
10847         R_Mesh_ResetTextureState();
10848         GL_Color(1, 1, 1, 1);
10849 }
10850
10851 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10852 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10853 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10854 {
10855         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10856                 return;
10857         if (prepass)
10858         {
10859                 // render screenspace normalmap to texture
10860                 GL_DepthMask(true);
10861                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10862                 RSurf_DrawBatch();
10863                 return;
10864         }
10865
10866         // bind lightmap texture
10867
10868         // water/refraction/reflection/camera surfaces have to be handled specially
10869         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10870         {
10871                 int start, end, startplaneindex;
10872                 for (start = 0;start < texturenumsurfaces;start = end)
10873                 {
10874                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10875                         if(startplaneindex < 0)
10876                         {
10877                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10878                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10879                                 end = start + 1;
10880                                 continue;
10881                         }
10882                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10883                                 ;
10884                         // now that we have a batch using the same planeindex, render it
10885                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10886                         {
10887                                 // render water or distortion background
10888                                 GL_DepthMask(true);
10889                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10890                                 RSurf_DrawBatch();
10891                                 // blend surface on top
10892                                 GL_DepthMask(false);
10893                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10894                                 RSurf_DrawBatch();
10895                         }
10896                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10897                         {
10898                                 // render surface with reflection texture as input
10899                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10900                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10901                                 RSurf_DrawBatch();
10902                         }
10903                 }
10904                 return;
10905         }
10906
10907         // render surface batch normally
10908         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10909         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10910         RSurf_DrawBatch();
10911 }
10912
10913 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10914 {
10915         // OpenGL 1.3 path - anything not completely ancient
10916         qboolean applycolor;
10917         qboolean applyfog;
10918         int layerindex;
10919         const texturelayer_t *layer;
10920         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10921         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10922
10923         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10924         {
10925                 vec4_t layercolor;
10926                 int layertexrgbscale;
10927                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10928                 {
10929                         if (layerindex == 0)
10930                                 GL_AlphaTest(true);
10931                         else
10932                         {
10933                                 GL_AlphaTest(false);
10934                                 GL_DepthFunc(GL_EQUAL);
10935                         }
10936                 }
10937                 GL_DepthMask(layer->depthmask && writedepth);
10938                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10939                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10940                 {
10941                         layertexrgbscale = 4;
10942                         VectorScale(layer->color, 0.25f, layercolor);
10943                 }
10944                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10945                 {
10946                         layertexrgbscale = 2;
10947                         VectorScale(layer->color, 0.5f, layercolor);
10948                 }
10949                 else
10950                 {
10951                         layertexrgbscale = 1;
10952                         VectorScale(layer->color, 1.0f, layercolor);
10953                 }
10954                 layercolor[3] = layer->color[3];
10955                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10956                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10957                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10958                 switch (layer->type)
10959                 {
10960                 case TEXTURELAYERTYPE_LITTEXTURE:
10961                         // single-pass lightmapped texture with 2x rgbscale
10962                         R_Mesh_TexBind(0, r_texture_white);
10963                         R_Mesh_TexMatrix(0, NULL);
10964                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10965                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10966                         R_Mesh_TexBind(1, layer->texture);
10967                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10968                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10969                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10970                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10971                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10972                         else if (FAKELIGHT_ENABLED)
10973                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10974                         else if (rsurface.uselightmaptexture)
10975                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10976                         else
10977                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10978                         break;
10979                 case TEXTURELAYERTYPE_TEXTURE:
10980                         // singletexture unlit texture with transparency support
10981                         R_Mesh_TexBind(0, layer->texture);
10982                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10983                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10984                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10985                         R_Mesh_TexBind(1, 0);
10986                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10987                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10988                         break;
10989                 case TEXTURELAYERTYPE_FOG:
10990                         // singletexture fogging
10991                         if (layer->texture)
10992                         {
10993                                 R_Mesh_TexBind(0, layer->texture);
10994                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10995                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10996                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10997                         }
10998                         else
10999                         {
11000                                 R_Mesh_TexBind(0, 0);
11001                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11002                         }
11003                         R_Mesh_TexBind(1, 0);
11004                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11005                         // generate a color array for the fog pass
11006                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11007                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11008                         RSurf_DrawBatch();
11009                         break;
11010                 default:
11011                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11012                 }
11013         }
11014         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11015         {
11016                 GL_DepthFunc(GL_LEQUAL);
11017                 GL_AlphaTest(false);
11018         }
11019 }
11020
11021 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11022 {
11023         // OpenGL 1.1 - crusty old voodoo path
11024         qboolean applyfog;
11025         int layerindex;
11026         const texturelayer_t *layer;
11027         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11028         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11029
11030         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11031         {
11032                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11033                 {
11034                         if (layerindex == 0)
11035                                 GL_AlphaTest(true);
11036                         else
11037                         {
11038                                 GL_AlphaTest(false);
11039                                 GL_DepthFunc(GL_EQUAL);
11040                         }
11041                 }
11042                 GL_DepthMask(layer->depthmask && writedepth);
11043                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11044                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11045                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11046                 switch (layer->type)
11047                 {
11048                 case TEXTURELAYERTYPE_LITTEXTURE:
11049                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11050                         {
11051                                 // two-pass lit texture with 2x rgbscale
11052                                 // first the lightmap pass
11053                                 R_Mesh_TexBind(0, r_texture_white);
11054                                 R_Mesh_TexMatrix(0, NULL);
11055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11057                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11058                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11059                                 else if (FAKELIGHT_ENABLED)
11060                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11061                                 else if (rsurface.uselightmaptexture)
11062                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11063                                 else
11064                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11065                                 // then apply the texture to it
11066                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11067                                 R_Mesh_TexBind(0, layer->texture);
11068                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11069                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11070                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11071                                 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);
11072                         }
11073                         else
11074                         {
11075                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11076                                 R_Mesh_TexBind(0, layer->texture);
11077                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11078                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11079                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11080                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11081                                         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);
11082                                 else if (FAKELIGHT_ENABLED)
11083                                         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);
11084                                 else
11085                                         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);
11086                         }
11087                         break;
11088                 case TEXTURELAYERTYPE_TEXTURE:
11089                         // singletexture unlit texture with transparency support
11090                         R_Mesh_TexBind(0, layer->texture);
11091                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11092                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11093                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11094                         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);
11095                         break;
11096                 case TEXTURELAYERTYPE_FOG:
11097                         // singletexture fogging
11098                         if (layer->texture)
11099                         {
11100                                 R_Mesh_TexBind(0, layer->texture);
11101                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11102                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11103                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11104                         }
11105                         else
11106                         {
11107                                 R_Mesh_TexBind(0, 0);
11108                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11109                         }
11110                         // generate a color array for the fog pass
11111                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11112                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11113                         RSurf_DrawBatch();
11114                         break;
11115                 default:
11116                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11117                 }
11118         }
11119         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11120         {
11121                 GL_DepthFunc(GL_LEQUAL);
11122                 GL_AlphaTest(false);
11123         }
11124 }
11125
11126 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11127 {
11128         int vi;
11129         int j;
11130         r_vertexgeneric_t *batchvertex;
11131         float c[4];
11132
11133 //      R_Mesh_ResetTextureState();
11134         R_SetupShader_Generic_NoTexture(false, false);
11135
11136         if(rsurface.texture && rsurface.texture->currentskinframe)
11137         {
11138                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11139                 c[3] *= rsurface.texture->currentalpha;
11140         }
11141         else
11142         {
11143                 c[0] = 1;
11144                 c[1] = 0;
11145                 c[2] = 1;
11146                 c[3] = 1;
11147         }
11148
11149         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11150         {
11151                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11152                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11153                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11154         }
11155
11156         // brighten it up (as texture value 127 means "unlit")
11157         c[0] *= 2 * r_refdef.view.colorscale;
11158         c[1] *= 2 * r_refdef.view.colorscale;
11159         c[2] *= 2 * r_refdef.view.colorscale;
11160
11161         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11162                 c[3] *= r_wateralpha.value;
11163
11164         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11165         {
11166                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11167                 GL_DepthMask(false);
11168         }
11169         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11170         {
11171                 GL_BlendFunc(GL_ONE, GL_ONE);
11172                 GL_DepthMask(false);
11173         }
11174         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11175         {
11176                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11177                 GL_DepthMask(false);
11178         }
11179         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11180         {
11181                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11182                 GL_DepthMask(false);
11183         }
11184         else
11185         {
11186                 GL_BlendFunc(GL_ONE, GL_ZERO);
11187                 GL_DepthMask(writedepth);
11188         }
11189
11190         if (r_showsurfaces.integer == 3)
11191         {
11192                 rsurface.passcolor4f = NULL;
11193
11194                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11195                 {
11196                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11197
11198                         rsurface.passcolor4f = NULL;
11199                         rsurface.passcolor4f_vertexbuffer = 0;
11200                         rsurface.passcolor4f_bufferoffset = 0;
11201                 }
11202                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11203                 {
11204                         qboolean applycolor = true;
11205                         float one = 1.0;
11206
11207                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11208
11209                         r_refdef.lightmapintensity = 1;
11210                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11211                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11212                 }
11213                 else if (FAKELIGHT_ENABLED)
11214                 {
11215                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11216
11217                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11218                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11219                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11220                 }
11221                 else
11222                 {
11223                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11224
11225                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11226                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11227                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11228                 }
11229
11230                 if(!rsurface.passcolor4f)
11231                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11232
11233                 RSurf_DrawBatch_GL11_ApplyAmbient();
11234                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11235                 if(r_refdef.fogenabled)
11236                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11237                 RSurf_DrawBatch_GL11_ClampColor();
11238
11239                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11240                 R_SetupShader_Generic_NoTexture(false, false);
11241                 RSurf_DrawBatch();
11242         }
11243         else if (!r_refdef.view.showdebug)
11244         {
11245                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11246                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11247                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11248                 {
11249                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11250                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11251                 }
11252                 R_Mesh_PrepareVertices_Generic_Unlock();
11253                 RSurf_DrawBatch();
11254         }
11255         else if (r_showsurfaces.integer == 4)
11256         {
11257                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11258                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11259                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11260                 {
11261                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11262                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11263                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11264                 }
11265                 R_Mesh_PrepareVertices_Generic_Unlock();
11266                 RSurf_DrawBatch();
11267         }
11268         else if (r_showsurfaces.integer == 2)
11269         {
11270                 const int *e;
11271                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11272                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11273                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11274                 {
11275                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11276                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11277                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11278                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11279                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11280                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11281                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11282                 }
11283                 R_Mesh_PrepareVertices_Generic_Unlock();
11284                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11285         }
11286         else
11287         {
11288                 int texturesurfaceindex;
11289                 int k;
11290                 const msurface_t *surface;
11291                 float surfacecolor4f[4];
11292                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11293                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11294                 vi = 0;
11295                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11296                 {
11297                         surface = texturesurfacelist[texturesurfaceindex];
11298                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11299                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11300                         for (j = 0;j < surface->num_vertices;j++)
11301                         {
11302                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11303                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11304                                 vi++;
11305                         }
11306                 }
11307                 R_Mesh_PrepareVertices_Generic_Unlock();
11308                 RSurf_DrawBatch();
11309         }
11310 }
11311
11312 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11313 {
11314         CHECKGLERROR
11315         RSurf_SetupDepthAndCulling();
11316         if (r_showsurfaces.integer)
11317         {
11318                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11319                 return;
11320         }
11321         switch (vid.renderpath)
11322         {
11323         case RENDERPATH_GL20:
11324         case RENDERPATH_D3D9:
11325         case RENDERPATH_D3D10:
11326         case RENDERPATH_D3D11:
11327         case RENDERPATH_SOFT:
11328         case RENDERPATH_GLES2:
11329                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11330                 break;
11331         case RENDERPATH_GL13:
11332         case RENDERPATH_GLES1:
11333                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11334                 break;
11335         case RENDERPATH_GL11:
11336                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11337                 break;
11338         }
11339         CHECKGLERROR
11340 }
11341
11342 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11343 {
11344         CHECKGLERROR
11345         RSurf_SetupDepthAndCulling();
11346         if (r_showsurfaces.integer)
11347         {
11348                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11349                 return;
11350         }
11351         switch (vid.renderpath)
11352         {
11353         case RENDERPATH_GL20:
11354         case RENDERPATH_D3D9:
11355         case RENDERPATH_D3D10:
11356         case RENDERPATH_D3D11:
11357         case RENDERPATH_SOFT:
11358         case RENDERPATH_GLES2:
11359                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11360                 break;
11361         case RENDERPATH_GL13:
11362         case RENDERPATH_GLES1:
11363                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11364                 break;
11365         case RENDERPATH_GL11:
11366                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11367                 break;
11368         }
11369         CHECKGLERROR
11370 }
11371
11372 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11373 {
11374         int i, j;
11375         int texturenumsurfaces, endsurface;
11376         texture_t *texture;
11377         const msurface_t *surface;
11378         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11379
11380         // if the model is static it doesn't matter what value we give for
11381         // wantnormals and wanttangents, so this logic uses only rules applicable
11382         // to a model, knowing that they are meaningless otherwise
11383         if (ent == r_refdef.scene.worldentity)
11384                 RSurf_ActiveWorldEntity();
11385         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11386                 RSurf_ActiveModelEntity(ent, false, false, false);
11387         else
11388         {
11389                 switch (vid.renderpath)
11390                 {
11391                 case RENDERPATH_GL20:
11392                 case RENDERPATH_D3D9:
11393                 case RENDERPATH_D3D10:
11394                 case RENDERPATH_D3D11:
11395                 case RENDERPATH_SOFT:
11396                 case RENDERPATH_GLES2:
11397                         RSurf_ActiveModelEntity(ent, true, true, false);
11398                         break;
11399                 case RENDERPATH_GL11:
11400                 case RENDERPATH_GL13:
11401                 case RENDERPATH_GLES1:
11402                         RSurf_ActiveModelEntity(ent, true, false, false);
11403                         break;
11404                 }
11405         }
11406
11407         if (r_transparentdepthmasking.integer)
11408         {
11409                 qboolean setup = false;
11410                 for (i = 0;i < numsurfaces;i = j)
11411                 {
11412                         j = i + 1;
11413                         surface = rsurface.modelsurfaces + surfacelist[i];
11414                         texture = surface->texture;
11415                         rsurface.texture = R_GetCurrentTexture(texture);
11416                         rsurface.lightmaptexture = NULL;
11417                         rsurface.deluxemaptexture = NULL;
11418                         rsurface.uselightmaptexture = false;
11419                         // scan ahead until we find a different texture
11420                         endsurface = min(i + 1024, numsurfaces);
11421                         texturenumsurfaces = 0;
11422                         texturesurfacelist[texturenumsurfaces++] = surface;
11423                         for (;j < endsurface;j++)
11424                         {
11425                                 surface = rsurface.modelsurfaces + surfacelist[j];
11426                                 if (texture != surface->texture)
11427                                         break;
11428                                 texturesurfacelist[texturenumsurfaces++] = surface;
11429                         }
11430                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11431                                 continue;
11432                         // render the range of surfaces as depth
11433                         if (!setup)
11434                         {
11435                                 setup = true;
11436                                 GL_ColorMask(0,0,0,0);
11437                                 GL_Color(1,1,1,1);
11438                                 GL_DepthTest(true);
11439                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11440                                 GL_DepthMask(true);
11441 //                              R_Mesh_ResetTextureState();
11442                         }
11443                         RSurf_SetupDepthAndCulling();
11444                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11445                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11446                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11447                         RSurf_DrawBatch();
11448                 }
11449                 if (setup)
11450                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11451         }
11452
11453         for (i = 0;i < numsurfaces;i = j)
11454         {
11455                 j = i + 1;
11456                 surface = rsurface.modelsurfaces + surfacelist[i];
11457                 texture = surface->texture;
11458                 rsurface.texture = R_GetCurrentTexture(texture);
11459                 // scan ahead until we find a different texture
11460                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11461                 texturenumsurfaces = 0;
11462                 texturesurfacelist[texturenumsurfaces++] = surface;
11463                 if(FAKELIGHT_ENABLED)
11464                 {
11465                         rsurface.lightmaptexture = NULL;
11466                         rsurface.deluxemaptexture = NULL;
11467                         rsurface.uselightmaptexture = false;
11468                         for (;j < endsurface;j++)
11469                         {
11470                                 surface = rsurface.modelsurfaces + surfacelist[j];
11471                                 if (texture != surface->texture)
11472                                         break;
11473                                 texturesurfacelist[texturenumsurfaces++] = surface;
11474                         }
11475                 }
11476                 else
11477                 {
11478                         rsurface.lightmaptexture = surface->lightmaptexture;
11479                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11480                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11481                         for (;j < endsurface;j++)
11482                         {
11483                                 surface = rsurface.modelsurfaces + surfacelist[j];
11484                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11485                                         break;
11486                                 texturesurfacelist[texturenumsurfaces++] = surface;
11487                         }
11488                 }
11489                 // render the range of surfaces
11490                 if (ent == r_refdef.scene.worldentity)
11491                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11492                 else
11493                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11494         }
11495         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11496 }
11497
11498 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11499 {
11500         // transparent surfaces get pushed off into the transparent queue
11501         int surfacelistindex;
11502         const msurface_t *surface;
11503         vec3_t tempcenter, center;
11504         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11505         {
11506                 surface = texturesurfacelist[surfacelistindex];
11507                 if (r_transparent_sortsurfacesbynearest.integer)
11508                 {
11509                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11510                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11511                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11512                 }
11513                 else
11514                 {
11515                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11516                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11517                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11518                 }
11519                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11520                 if (rsurface.entity->transparent_offset) // transparent offset
11521                 {
11522                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11523                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11524                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11525                 }
11526                 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);
11527         }
11528 }
11529
11530 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11531 {
11532         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11533                 return;
11534         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11535                 return;
11536         RSurf_SetupDepthAndCulling();
11537         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11538         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11539         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11540         RSurf_DrawBatch();
11541 }
11542
11543 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11544 {
11545         CHECKGLERROR
11546         if (depthonly)
11547                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11548         else if (prepass)
11549         {
11550                 if (!rsurface.texture->currentnumlayers)
11551                         return;
11552                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11553                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11554                 else
11555                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11556         }
11557         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11558                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11559         else if (!rsurface.texture->currentnumlayers)
11560                 return;
11561         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11562         {
11563                 // in the deferred case, transparent surfaces were queued during prepass
11564                 if (!r_shadow_usingdeferredprepass)
11565                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11566         }
11567         else
11568         {
11569                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11570                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11571         }
11572         CHECKGLERROR
11573 }
11574
11575 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11576 {
11577         int i, j;
11578         texture_t *texture;
11579         R_FrameData_SetMark();
11580         // break the surface list down into batches by texture and use of lightmapping
11581         for (i = 0;i < numsurfaces;i = j)
11582         {
11583                 j = i + 1;
11584                 // texture is the base texture pointer, rsurface.texture is the
11585                 // current frame/skin the texture is directing us to use (for example
11586                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11587                 // use skin 1 instead)
11588                 texture = surfacelist[i]->texture;
11589                 rsurface.texture = R_GetCurrentTexture(texture);
11590                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11591                 {
11592                         // if this texture is not the kind we want, skip ahead to the next one
11593                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11594                                 ;
11595                         continue;
11596                 }
11597                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11598                 {
11599                         rsurface.lightmaptexture = NULL;
11600                         rsurface.deluxemaptexture = NULL;
11601                         rsurface.uselightmaptexture = false;
11602                         // simply scan ahead until we find a different texture or lightmap state
11603                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11604                                 ;
11605                 }
11606                 else
11607                 {
11608                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11609                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11610                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11611                         // simply scan ahead until we find a different texture or lightmap state
11612                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11613                                 ;
11614                 }
11615                 // render the range of surfaces
11616                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11617         }
11618         R_FrameData_ReturnToMark();
11619 }
11620
11621 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11622 {
11623         CHECKGLERROR
11624         if (depthonly)
11625                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11626         else if (prepass)
11627         {
11628                 if (!rsurface.texture->currentnumlayers)
11629                         return;
11630                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11631                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11632                 else
11633                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11634         }
11635         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11636                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11637         else if (!rsurface.texture->currentnumlayers)
11638                 return;
11639         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11640         {
11641                 // in the deferred case, transparent surfaces were queued during prepass
11642                 if (!r_shadow_usingdeferredprepass)
11643                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11644         }
11645         else
11646         {
11647                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11648                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11649         }
11650         CHECKGLERROR
11651 }
11652
11653 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11654 {
11655         int i, j;
11656         texture_t *texture;
11657         R_FrameData_SetMark();
11658         // break the surface list down into batches by texture and use of lightmapping
11659         for (i = 0;i < numsurfaces;i = j)
11660         {
11661                 j = i + 1;
11662                 // texture is the base texture pointer, rsurface.texture is the
11663                 // current frame/skin the texture is directing us to use (for example
11664                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11665                 // use skin 1 instead)
11666                 texture = surfacelist[i]->texture;
11667                 rsurface.texture = R_GetCurrentTexture(texture);
11668                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11669                 {
11670                         // if this texture is not the kind we want, skip ahead to the next one
11671                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11672                                 ;
11673                         continue;
11674                 }
11675                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11676                 {
11677                         rsurface.lightmaptexture = NULL;
11678                         rsurface.deluxemaptexture = NULL;
11679                         rsurface.uselightmaptexture = false;
11680                         // simply scan ahead until we find a different texture or lightmap state
11681                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11682                                 ;
11683                 }
11684                 else
11685                 {
11686                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11687                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11688                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11689                         // simply scan ahead until we find a different texture or lightmap state
11690                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11691                                 ;
11692                 }
11693                 // render the range of surfaces
11694                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11695         }
11696         R_FrameData_ReturnToMark();
11697 }
11698
11699 float locboxvertex3f[6*4*3] =
11700 {
11701         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11702         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11703         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11704         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11705         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11706         1,0,0, 0,0,0, 0,1,0, 1,1,0
11707 };
11708
11709 unsigned short locboxelements[6*2*3] =
11710 {
11711          0, 1, 2, 0, 2, 3,
11712          4, 5, 6, 4, 6, 7,
11713          8, 9,10, 8,10,11,
11714         12,13,14, 12,14,15,
11715         16,17,18, 16,18,19,
11716         20,21,22, 20,22,23
11717 };
11718
11719 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11720 {
11721         int i, j;
11722         cl_locnode_t *loc = (cl_locnode_t *)ent;
11723         vec3_t mins, size;
11724         float vertex3f[6*4*3];
11725         CHECKGLERROR
11726         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11727         GL_DepthMask(false);
11728         GL_DepthRange(0, 1);
11729         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11730         GL_DepthTest(true);
11731         GL_CullFace(GL_NONE);
11732         R_EntityMatrix(&identitymatrix);
11733
11734 //      R_Mesh_ResetTextureState();
11735
11736         i = surfacelist[0];
11737         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11738                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11739                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11740                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11741
11742         if (VectorCompare(loc->mins, loc->maxs))
11743         {
11744                 VectorSet(size, 2, 2, 2);
11745                 VectorMA(loc->mins, -0.5f, size, mins);
11746         }
11747         else
11748         {
11749                 VectorCopy(loc->mins, mins);
11750                 VectorSubtract(loc->maxs, loc->mins, size);
11751         }
11752
11753         for (i = 0;i < 6*4*3;)
11754                 for (j = 0;j < 3;j++, i++)
11755                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11756
11757         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11758         R_SetupShader_Generic_NoTexture(false, false);
11759         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11760 }
11761
11762 void R_DrawLocs(void)
11763 {
11764         int index;
11765         cl_locnode_t *loc, *nearestloc;
11766         vec3_t center;
11767         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11768         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11769         {
11770                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11771                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11772         }
11773 }
11774
11775 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11776 {
11777         if (decalsystem->decals)
11778                 Mem_Free(decalsystem->decals);
11779         memset(decalsystem, 0, sizeof(*decalsystem));
11780 }
11781
11782 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)
11783 {
11784         tridecal_t *decal;
11785         tridecal_t *decals;
11786         int i;
11787
11788         // expand or initialize the system
11789         if (decalsystem->maxdecals <= decalsystem->numdecals)
11790         {
11791                 decalsystem_t old = *decalsystem;
11792                 qboolean useshortelements;
11793                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11794                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11795                 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)));
11796                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11797                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11798                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11799                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11800                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11801                 if (decalsystem->numdecals)
11802                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11803                 if (old.decals)
11804                         Mem_Free(old.decals);
11805                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11806                         decalsystem->element3i[i] = i;
11807                 if (useshortelements)
11808                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11809                                 decalsystem->element3s[i] = i;
11810         }
11811
11812         // grab a decal and search for another free slot for the next one
11813         decals = decalsystem->decals;
11814         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11815         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11816                 ;
11817         decalsystem->freedecal = i;
11818         if (decalsystem->numdecals <= i)
11819                 decalsystem->numdecals = i + 1;
11820
11821         // initialize the decal
11822         decal->lived = 0;
11823         decal->triangleindex = triangleindex;
11824         decal->surfaceindex = surfaceindex;
11825         decal->decalsequence = decalsequence;
11826         decal->color4f[0][0] = c0[0];
11827         decal->color4f[0][1] = c0[1];
11828         decal->color4f[0][2] = c0[2];
11829         decal->color4f[0][3] = 1;
11830         decal->color4f[1][0] = c1[0];
11831         decal->color4f[1][1] = c1[1];
11832         decal->color4f[1][2] = c1[2];
11833         decal->color4f[1][3] = 1;
11834         decal->color4f[2][0] = c2[0];
11835         decal->color4f[2][1] = c2[1];
11836         decal->color4f[2][2] = c2[2];
11837         decal->color4f[2][3] = 1;
11838         decal->vertex3f[0][0] = v0[0];
11839         decal->vertex3f[0][1] = v0[1];
11840         decal->vertex3f[0][2] = v0[2];
11841         decal->vertex3f[1][0] = v1[0];
11842         decal->vertex3f[1][1] = v1[1];
11843         decal->vertex3f[1][2] = v1[2];
11844         decal->vertex3f[2][0] = v2[0];
11845         decal->vertex3f[2][1] = v2[1];
11846         decal->vertex3f[2][2] = v2[2];
11847         decal->texcoord2f[0][0] = t0[0];
11848         decal->texcoord2f[0][1] = t0[1];
11849         decal->texcoord2f[1][0] = t1[0];
11850         decal->texcoord2f[1][1] = t1[1];
11851         decal->texcoord2f[2][0] = t2[0];
11852         decal->texcoord2f[2][1] = t2[1];
11853         TriangleNormal(v0, v1, v2, decal->plane);
11854         VectorNormalize(decal->plane);
11855         decal->plane[3] = DotProduct(v0, decal->plane);
11856 }
11857
11858 extern cvar_t cl_decals_bias;
11859 extern cvar_t cl_decals_models;
11860 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11861 // baseparms, parms, temps
11862 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)
11863 {
11864         int cornerindex;
11865         int index;
11866         float v[9][3];
11867         const float *vertex3f;
11868         const float *normal3f;
11869         int numpoints;
11870         float points[2][9][3];
11871         float temp[3];
11872         float tc[9][2];
11873         float f;
11874         float c[9][4];
11875         const int *e;
11876
11877         e = rsurface.modelelement3i + 3*triangleindex;
11878
11879         vertex3f = rsurface.modelvertex3f;
11880         normal3f = rsurface.modelnormal3f;
11881
11882         if (normal3f)
11883         {
11884                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11885                 {
11886                         index = 3*e[cornerindex];
11887                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11888                 }
11889         }
11890         else
11891         {
11892                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11893                 {
11894                         index = 3*e[cornerindex];
11895                         VectorCopy(vertex3f + index, v[cornerindex]);
11896                 }
11897         }
11898
11899         // cull backfaces
11900         //TriangleNormal(v[0], v[1], v[2], normal);
11901         //if (DotProduct(normal, localnormal) < 0.0f)
11902         //      continue;
11903         // clip by each of the box planes formed from the projection matrix
11904         // if anything survives, we emit the decal
11905         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]);
11906         if (numpoints < 3)
11907                 return;
11908         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]);
11909         if (numpoints < 3)
11910                 return;
11911         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]);
11912         if (numpoints < 3)
11913                 return;
11914         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]);
11915         if (numpoints < 3)
11916                 return;
11917         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]);
11918         if (numpoints < 3)
11919                 return;
11920         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]);
11921         if (numpoints < 3)
11922                 return;
11923         // some part of the triangle survived, so we have to accept it...
11924         if (dynamic)
11925         {
11926                 // dynamic always uses the original triangle
11927                 numpoints = 3;
11928                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11929                 {
11930                         index = 3*e[cornerindex];
11931                         VectorCopy(vertex3f + index, v[cornerindex]);
11932                 }
11933         }
11934         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11935         {
11936                 // convert vertex positions to texcoords
11937                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11938                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11939                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11940                 // calculate distance fade from the projection origin
11941                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11942                 f = bound(0.0f, f, 1.0f);
11943                 c[cornerindex][0] = r * f;
11944                 c[cornerindex][1] = g * f;
11945                 c[cornerindex][2] = b * f;
11946                 c[cornerindex][3] = 1.0f;
11947                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11948         }
11949         if (dynamic)
11950                 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);
11951         else
11952                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11953                         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);
11954 }
11955 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)
11956 {
11957         matrix4x4_t projection;
11958         decalsystem_t *decalsystem;
11959         qboolean dynamic;
11960         dp_model_t *model;
11961         const msurface_t *surface;
11962         const msurface_t *surfaces;
11963         const int *surfacelist;
11964         const texture_t *texture;
11965         int numtriangles;
11966         int numsurfacelist;
11967         int surfacelistindex;
11968         int surfaceindex;
11969         int triangleindex;
11970         float localorigin[3];
11971         float localnormal[3];
11972         float localmins[3];
11973         float localmaxs[3];
11974         float localsize;
11975         //float normal[3];
11976         float planes[6][4];
11977         float angles[3];
11978         bih_t *bih;
11979         int bih_triangles_count;
11980         int bih_triangles[256];
11981         int bih_surfaces[256];
11982
11983         decalsystem = &ent->decalsystem;
11984         model = ent->model;
11985         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11986         {
11987                 R_DecalSystem_Reset(&ent->decalsystem);
11988                 return;
11989         }
11990
11991         if (!model->brush.data_leafs && !cl_decals_models.integer)
11992         {
11993                 if (decalsystem->model)
11994                         R_DecalSystem_Reset(decalsystem);
11995                 return;
11996         }
11997
11998         if (decalsystem->model != model)
11999                 R_DecalSystem_Reset(decalsystem);
12000         decalsystem->model = model;
12001
12002         RSurf_ActiveModelEntity(ent, true, false, false);
12003
12004         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12005         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12006         VectorNormalize(localnormal);
12007         localsize = worldsize*rsurface.inversematrixscale;
12008         localmins[0] = localorigin[0] - localsize;
12009         localmins[1] = localorigin[1] - localsize;
12010         localmins[2] = localorigin[2] - localsize;
12011         localmaxs[0] = localorigin[0] + localsize;
12012         localmaxs[1] = localorigin[1] + localsize;
12013         localmaxs[2] = localorigin[2] + localsize;
12014
12015         //VectorCopy(localnormal, planes[4]);
12016         //VectorVectors(planes[4], planes[2], planes[0]);
12017         AnglesFromVectors(angles, localnormal, NULL, false);
12018         AngleVectors(angles, planes[0], planes[2], planes[4]);
12019         VectorNegate(planes[0], planes[1]);
12020         VectorNegate(planes[2], planes[3]);
12021         VectorNegate(planes[4], planes[5]);
12022         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12023         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12024         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12025         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12026         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12027         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12028
12029 #if 1
12030 // works
12031 {
12032         matrix4x4_t forwardprojection;
12033         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12034         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12035 }
12036 #else
12037 // broken
12038 {
12039         float projectionvector[4][3];
12040         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12041         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12042         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12043         projectionvector[0][0] = planes[0][0] * ilocalsize;
12044         projectionvector[0][1] = planes[1][0] * ilocalsize;
12045         projectionvector[0][2] = planes[2][0] * ilocalsize;
12046         projectionvector[1][0] = planes[0][1] * ilocalsize;
12047         projectionvector[1][1] = planes[1][1] * ilocalsize;
12048         projectionvector[1][2] = planes[2][1] * ilocalsize;
12049         projectionvector[2][0] = planes[0][2] * ilocalsize;
12050         projectionvector[2][1] = planes[1][2] * ilocalsize;
12051         projectionvector[2][2] = planes[2][2] * ilocalsize;
12052         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12053         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12054         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12055         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12056 }
12057 #endif
12058
12059         dynamic = model->surfmesh.isanimated;
12060         numsurfacelist = model->nummodelsurfaces;
12061         surfacelist = model->sortedmodelsurfaces;
12062         surfaces = model->data_surfaces;
12063
12064         bih = NULL;
12065         bih_triangles_count = -1;
12066         if(!dynamic)
12067         {
12068                 if(model->render_bih.numleafs)
12069                         bih = &model->render_bih;
12070                 else if(model->collision_bih.numleafs)
12071                         bih = &model->collision_bih;
12072         }
12073         if(bih)
12074                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12075         if(bih_triangles_count == 0)
12076                 return;
12077         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12078                 return;
12079         if(bih_triangles_count > 0)
12080         {
12081                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12082                 {
12083                         surfaceindex = bih_surfaces[triangleindex];
12084                         surface = surfaces + surfaceindex;
12085                         texture = surface->texture;
12086                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12087                                 continue;
12088                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12089                                 continue;
12090                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12091                 }
12092         }
12093         else
12094         {
12095                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12096                 {
12097                         surfaceindex = surfacelist[surfacelistindex];
12098                         surface = surfaces + surfaceindex;
12099                         // check cull box first because it rejects more than any other check
12100                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12101                                 continue;
12102                         // skip transparent surfaces
12103                         texture = surface->texture;
12104                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12105                                 continue;
12106                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12107                                 continue;
12108                         numtriangles = surface->num_triangles;
12109                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12110                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12111                 }
12112         }
12113 }
12114
12115 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12116 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)
12117 {
12118         int renderentityindex;
12119         float worldmins[3];
12120         float worldmaxs[3];
12121         entity_render_t *ent;
12122
12123         if (!cl_decals_newsystem.integer)
12124                 return;
12125
12126         worldmins[0] = worldorigin[0] - worldsize;
12127         worldmins[1] = worldorigin[1] - worldsize;
12128         worldmins[2] = worldorigin[2] - worldsize;
12129         worldmaxs[0] = worldorigin[0] + worldsize;
12130         worldmaxs[1] = worldorigin[1] + worldsize;
12131         worldmaxs[2] = worldorigin[2] + worldsize;
12132
12133         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12134
12135         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12136         {
12137                 ent = r_refdef.scene.entities[renderentityindex];
12138                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12139                         continue;
12140
12141                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12142         }
12143 }
12144
12145 typedef struct r_decalsystem_splatqueue_s
12146 {
12147         vec3_t worldorigin;
12148         vec3_t worldnormal;
12149         float color[4];
12150         float tcrange[4];
12151         float worldsize;
12152         unsigned int decalsequence;
12153 }
12154 r_decalsystem_splatqueue_t;
12155
12156 int r_decalsystem_numqueued = 0;
12157 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12158
12159 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)
12160 {
12161         r_decalsystem_splatqueue_t *queue;
12162
12163         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12164                 return;
12165
12166         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12167         VectorCopy(worldorigin, queue->worldorigin);
12168         VectorCopy(worldnormal, queue->worldnormal);
12169         Vector4Set(queue->color, r, g, b, a);
12170         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12171         queue->worldsize = worldsize;
12172         queue->decalsequence = cl.decalsequence++;
12173 }
12174
12175 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12176 {
12177         int i;
12178         r_decalsystem_splatqueue_t *queue;
12179
12180         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12181                 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);
12182         r_decalsystem_numqueued = 0;
12183 }
12184
12185 extern cvar_t cl_decals_max;
12186 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12187 {
12188         int i;
12189         decalsystem_t *decalsystem = &ent->decalsystem;
12190         int numdecals;
12191         unsigned int killsequence;
12192         tridecal_t *decal;
12193         float frametime;
12194         float lifetime;
12195
12196         if (!decalsystem->numdecals)
12197                 return;
12198
12199         if (r_showsurfaces.integer)
12200                 return;
12201
12202         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12203         {
12204                 R_DecalSystem_Reset(decalsystem);
12205                 return;
12206         }
12207
12208         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12209         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12210
12211         if (decalsystem->lastupdatetime)
12212                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12213         else
12214                 frametime = 0;
12215         decalsystem->lastupdatetime = r_refdef.scene.time;
12216         numdecals = decalsystem->numdecals;
12217
12218         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12219         {
12220                 if (decal->color4f[0][3])
12221                 {
12222                         decal->lived += frametime;
12223                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12224                         {
12225                                 memset(decal, 0, sizeof(*decal));
12226                                 if (decalsystem->freedecal > i)
12227                                         decalsystem->freedecal = i;
12228                         }
12229                 }
12230         }
12231         decal = decalsystem->decals;
12232         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12233                 numdecals--;
12234
12235         // collapse the array by shuffling the tail decals into the gaps
12236         for (;;)
12237         {
12238                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12239                         decalsystem->freedecal++;
12240                 if (decalsystem->freedecal == numdecals)
12241                         break;
12242                 decal[decalsystem->freedecal] = decal[--numdecals];
12243         }
12244
12245         decalsystem->numdecals = numdecals;
12246
12247         if (numdecals <= 0)
12248         {
12249                 // if there are no decals left, reset decalsystem
12250                 R_DecalSystem_Reset(decalsystem);
12251         }
12252 }
12253
12254 extern skinframe_t *decalskinframe;
12255 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12256 {
12257         int i;
12258         decalsystem_t *decalsystem = &ent->decalsystem;
12259         int numdecals;
12260         tridecal_t *decal;
12261         float faderate;
12262         float alpha;
12263         float *v3f;
12264         float *c4f;
12265         float *t2f;
12266         const int *e;
12267         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12268         int numtris = 0;
12269
12270         numdecals = decalsystem->numdecals;
12271         if (!numdecals)
12272                 return;
12273
12274         if (r_showsurfaces.integer)
12275                 return;
12276
12277         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12278         {
12279                 R_DecalSystem_Reset(decalsystem);
12280                 return;
12281         }
12282
12283         // if the model is static it doesn't matter what value we give for
12284         // wantnormals and wanttangents, so this logic uses only rules applicable
12285         // to a model, knowing that they are meaningless otherwise
12286         if (ent == r_refdef.scene.worldentity)
12287                 RSurf_ActiveWorldEntity();
12288         else
12289                 RSurf_ActiveModelEntity(ent, false, false, false);
12290
12291         decalsystem->lastupdatetime = r_refdef.scene.time;
12292
12293         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12294
12295         // update vertex positions for animated models
12296         v3f = decalsystem->vertex3f;
12297         c4f = decalsystem->color4f;
12298         t2f = decalsystem->texcoord2f;
12299         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12300         {
12301                 if (!decal->color4f[0][3])
12302                         continue;
12303
12304                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12305                         continue;
12306
12307                 // skip backfaces
12308                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12309                         continue;
12310
12311                 // update color values for fading decals
12312                 if (decal->lived >= cl_decals_time.value)
12313                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12314                 else
12315                         alpha = 1.0f;
12316
12317                 c4f[ 0] = decal->color4f[0][0] * alpha;
12318                 c4f[ 1] = decal->color4f[0][1] * alpha;
12319                 c4f[ 2] = decal->color4f[0][2] * alpha;
12320                 c4f[ 3] = 1;
12321                 c4f[ 4] = decal->color4f[1][0] * alpha;
12322                 c4f[ 5] = decal->color4f[1][1] * alpha;
12323                 c4f[ 6] = decal->color4f[1][2] * alpha;
12324                 c4f[ 7] = 1;
12325                 c4f[ 8] = decal->color4f[2][0] * alpha;
12326                 c4f[ 9] = decal->color4f[2][1] * alpha;
12327                 c4f[10] = decal->color4f[2][2] * alpha;
12328                 c4f[11] = 1;
12329
12330                 t2f[0] = decal->texcoord2f[0][0];
12331                 t2f[1] = decal->texcoord2f[0][1];
12332                 t2f[2] = decal->texcoord2f[1][0];
12333                 t2f[3] = decal->texcoord2f[1][1];
12334                 t2f[4] = decal->texcoord2f[2][0];
12335                 t2f[5] = decal->texcoord2f[2][1];
12336
12337                 // update vertex positions for animated models
12338                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12339                 {
12340                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12341                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12342                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12343                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12344                 }
12345                 else
12346                 {
12347                         VectorCopy(decal->vertex3f[0], v3f);
12348                         VectorCopy(decal->vertex3f[1], v3f + 3);
12349                         VectorCopy(decal->vertex3f[2], v3f + 6);
12350                 }
12351
12352                 if (r_refdef.fogenabled)
12353                 {
12354                         alpha = RSurf_FogVertex(v3f);
12355                         VectorScale(c4f, alpha, c4f);
12356                         alpha = RSurf_FogVertex(v3f + 3);
12357                         VectorScale(c4f + 4, alpha, c4f + 4);
12358                         alpha = RSurf_FogVertex(v3f + 6);
12359                         VectorScale(c4f + 8, alpha, c4f + 8);
12360                 }
12361
12362                 v3f += 9;
12363                 c4f += 12;
12364                 t2f += 6;
12365                 numtris++;
12366         }
12367
12368         if (numtris > 0)
12369         {
12370                 r_refdef.stats[r_stat_drawndecals] += numtris;
12371
12372                 // now render the decals all at once
12373                 // (this assumes they all use one particle font texture!)
12374                 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);
12375 //              R_Mesh_ResetTextureState();
12376                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12377                 GL_DepthMask(false);
12378                 GL_DepthRange(0, 1);
12379                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12380                 GL_DepthTest(true);
12381                 GL_CullFace(GL_NONE);
12382                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12383                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12384                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12385         }
12386 }
12387
12388 static void R_DrawModelDecals(void)
12389 {
12390         int i, numdecals;
12391
12392         // fade faster when there are too many decals
12393         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12394         for (i = 0;i < r_refdef.scene.numentities;i++)
12395                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12396
12397         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12398         for (i = 0;i < r_refdef.scene.numentities;i++)
12399                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12400                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12401
12402         R_DecalSystem_ApplySplatEntitiesQueue();
12403
12404         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12405         for (i = 0;i < r_refdef.scene.numentities;i++)
12406                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12407
12408         r_refdef.stats[r_stat_totaldecals] += numdecals;
12409
12410         if (r_showsurfaces.integer)
12411                 return;
12412
12413         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12414
12415         for (i = 0;i < r_refdef.scene.numentities;i++)
12416         {
12417                 if (!r_refdef.viewcache.entityvisible[i])
12418                         continue;
12419                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12420                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12421         }
12422 }
12423
12424 extern cvar_t mod_collision_bih;
12425 static void R_DrawDebugModel(void)
12426 {
12427         entity_render_t *ent = rsurface.entity;
12428         int i, j, flagsmask;
12429         const msurface_t *surface;
12430         dp_model_t *model = ent->model;
12431
12432         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12433                 return;
12434
12435         if (r_showoverdraw.value > 0)
12436         {
12437                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12438                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12439                 R_SetupShader_Generic_NoTexture(false, false);
12440                 GL_DepthTest(false);
12441                 GL_DepthMask(false);
12442                 GL_DepthRange(0, 1);
12443                 GL_BlendFunc(GL_ONE, GL_ONE);
12444                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12445                 {
12446                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12447                                 continue;
12448                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12449                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12450                         {
12451                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12452                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12453                                 if (!rsurface.texture->currentlayers->depthmask)
12454                                         GL_Color(c, 0, 0, 1.0f);
12455                                 else if (ent == r_refdef.scene.worldentity)
12456                                         GL_Color(c, c, c, 1.0f);
12457                                 else
12458                                         GL_Color(0, c, 0, 1.0f);
12459                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12460                                 RSurf_DrawBatch();
12461                         }
12462                 }
12463                 rsurface.texture = NULL;
12464         }
12465
12466         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12467
12468 //      R_Mesh_ResetTextureState();
12469         R_SetupShader_Generic_NoTexture(false, false);
12470         GL_DepthRange(0, 1);
12471         GL_DepthTest(!r_showdisabledepthtest.integer);
12472         GL_DepthMask(false);
12473         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12474
12475         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12476         {
12477                 int triangleindex;
12478                 int bihleafindex;
12479                 qboolean cullbox = false;
12480                 const q3mbrush_t *brush;
12481                 const bih_t *bih = &model->collision_bih;
12482                 const bih_leaf_t *bihleaf;
12483                 float vertex3f[3][3];
12484                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12485                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12486                 {
12487                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12488                                 continue;
12489                         switch (bihleaf->type)
12490                         {
12491                         case BIH_BRUSH:
12492                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12493                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12494                                 {
12495                                         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);
12496                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12497                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12498                                 }
12499                                 break;
12500                         case BIH_COLLISIONTRIANGLE:
12501                                 triangleindex = bihleaf->itemindex;
12502                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12503                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12504                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12505                                 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);
12506                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12507                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12508                                 break;
12509                         case BIH_RENDERTRIANGLE:
12510                                 triangleindex = bihleaf->itemindex;
12511                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12512                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12513                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12514                                 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);
12515                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12516                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12517                                 break;
12518                         }
12519                 }
12520         }
12521
12522         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12523
12524 #ifndef USE_GLES2
12525         if (r_showtris.integer && qglPolygonMode)
12526         {
12527                 if (r_showdisabledepthtest.integer)
12528                 {
12529                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12530                         GL_DepthMask(false);
12531                 }
12532                 else
12533                 {
12534                         GL_BlendFunc(GL_ONE, GL_ZERO);
12535                         GL_DepthMask(true);
12536                 }
12537                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12538                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12539                 {
12540                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12541                                 continue;
12542                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12543                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12544                         {
12545                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12546                                 if (!rsurface.texture->currentlayers->depthmask)
12547                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12548                                 else if (ent == r_refdef.scene.worldentity)
12549                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12550                                 else
12551                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12552                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12553                                 RSurf_DrawBatch();
12554                         }
12555                 }
12556                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12557                 rsurface.texture = NULL;
12558         }
12559
12560         if (r_shownormals.value != 0 && qglBegin)
12561         {
12562                 int l, k;
12563                 vec3_t v;
12564                 if (r_showdisabledepthtest.integer)
12565                 {
12566                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12567                         GL_DepthMask(false);
12568                 }
12569                 else
12570                 {
12571                         GL_BlendFunc(GL_ONE, GL_ZERO);
12572                         GL_DepthMask(true);
12573                 }
12574                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12575                 {
12576                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12577                                 continue;
12578                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12579                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12580                         {
12581                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12582                                 qglBegin(GL_LINES);
12583                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12584                                 {
12585                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12586                                         {
12587                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12588                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12589                                                 qglVertex3f(v[0], v[1], v[2]);
12590                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12591                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12592                                                 qglVertex3f(v[0], v[1], v[2]);
12593                                         }
12594                                 }
12595                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12596                                 {
12597                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12598                                         {
12599                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12600                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12601                                                 qglVertex3f(v[0], v[1], v[2]);
12602                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12603                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12604                                                 qglVertex3f(v[0], v[1], v[2]);
12605                                         }
12606                                 }
12607                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12608                                 {
12609                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12610                                         {
12611                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12612                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12613                                                 qglVertex3f(v[0], v[1], v[2]);
12614                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12615                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12616                                                 qglVertex3f(v[0], v[1], v[2]);
12617                                         }
12618                                 }
12619                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12620                                 {
12621                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12622                                         {
12623                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12624                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12625                                                 qglVertex3f(v[0], v[1], v[2]);
12626                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12627                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12628                                                 qglVertex3f(v[0], v[1], v[2]);
12629                                         }
12630                                 }
12631                                 qglEnd();
12632                                 CHECKGLERROR
12633                         }
12634                 }
12635                 rsurface.texture = NULL;
12636         }
12637 #endif
12638 }
12639
12640 int r_maxsurfacelist = 0;
12641 const msurface_t **r_surfacelist = NULL;
12642 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12643 {
12644         int i, j, endj, flagsmask;
12645         dp_model_t *model = r_refdef.scene.worldmodel;
12646         msurface_t *surfaces;
12647         unsigned char *update;
12648         int numsurfacelist = 0;
12649         if (model == NULL)
12650                 return;
12651
12652         if (r_maxsurfacelist < model->num_surfaces)
12653         {
12654                 r_maxsurfacelist = model->num_surfaces;
12655                 if (r_surfacelist)
12656                         Mem_Free((msurface_t**)r_surfacelist);
12657                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12658         }
12659
12660         RSurf_ActiveWorldEntity();
12661
12662         surfaces = model->data_surfaces;
12663         update = model->brushq1.lightmapupdateflags;
12664
12665         // update light styles on this submodel
12666         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12667         {
12668                 model_brush_lightstyleinfo_t *style;
12669                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12670                 {
12671                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12672                         {
12673                                 int *list = style->surfacelist;
12674                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12675                                 for (j = 0;j < style->numsurfaces;j++)
12676                                         update[list[j]] = true;
12677                         }
12678                 }
12679         }
12680
12681         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12682
12683         if (debug)
12684         {
12685                 R_DrawDebugModel();
12686                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12687                 return;
12688         }
12689
12690         rsurface.lightmaptexture = NULL;
12691         rsurface.deluxemaptexture = NULL;
12692         rsurface.uselightmaptexture = false;
12693         rsurface.texture = NULL;
12694         rsurface.rtlight = NULL;
12695         numsurfacelist = 0;
12696         // add visible surfaces to draw list
12697         for (i = 0;i < model->nummodelsurfaces;i++)
12698         {
12699                 j = model->sortedmodelsurfaces[i];
12700                 if (r_refdef.viewcache.world_surfacevisible[j])
12701                         r_surfacelist[numsurfacelist++] = surfaces + j;
12702         }
12703         // update lightmaps if needed
12704         if (model->brushq1.firstrender)
12705         {
12706                 model->brushq1.firstrender = false;
12707                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12708                         if (update[j])
12709                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12710         }
12711         else if (update)
12712         {
12713                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12714                         if (r_refdef.viewcache.world_surfacevisible[j])
12715                                 if (update[j])
12716                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12717         }
12718         // don't do anything if there were no surfaces
12719         if (!numsurfacelist)
12720         {
12721                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12722                 return;
12723         }
12724         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12725
12726         // add to stats if desired
12727         if (r_speeds.integer && !skysurfaces && !depthonly)
12728         {
12729                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12730                 for (j = 0;j < numsurfacelist;j++)
12731                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12732         }
12733
12734         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12735 }
12736
12737 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12738 {
12739         int i, j, endj, flagsmask;
12740         dp_model_t *model = ent->model;
12741         msurface_t *surfaces;
12742         unsigned char *update;
12743         int numsurfacelist = 0;
12744         if (model == NULL)
12745                 return;
12746
12747         if (r_maxsurfacelist < model->num_surfaces)
12748         {
12749                 r_maxsurfacelist = model->num_surfaces;
12750                 if (r_surfacelist)
12751                         Mem_Free((msurface_t **)r_surfacelist);
12752                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12753         }
12754
12755         // if the model is static it doesn't matter what value we give for
12756         // wantnormals and wanttangents, so this logic uses only rules applicable
12757         // to a model, knowing that they are meaningless otherwise
12758         if (ent == r_refdef.scene.worldentity)
12759                 RSurf_ActiveWorldEntity();
12760         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12761                 RSurf_ActiveModelEntity(ent, false, false, false);
12762         else if (prepass)
12763                 RSurf_ActiveModelEntity(ent, true, true, true);
12764         else if (depthonly)
12765         {
12766                 switch (vid.renderpath)
12767                 {
12768                 case RENDERPATH_GL20:
12769                 case RENDERPATH_D3D9:
12770                 case RENDERPATH_D3D10:
12771                 case RENDERPATH_D3D11:
12772                 case RENDERPATH_SOFT:
12773                 case RENDERPATH_GLES2:
12774                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12775                         break;
12776                 case RENDERPATH_GL11:
12777                 case RENDERPATH_GL13:
12778                 case RENDERPATH_GLES1:
12779                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12780                         break;
12781                 }
12782         }
12783         else
12784         {
12785                 switch (vid.renderpath)
12786                 {
12787                 case RENDERPATH_GL20:
12788                 case RENDERPATH_D3D9:
12789                 case RENDERPATH_D3D10:
12790                 case RENDERPATH_D3D11:
12791                 case RENDERPATH_SOFT:
12792                 case RENDERPATH_GLES2:
12793                         RSurf_ActiveModelEntity(ent, true, true, false);
12794                         break;
12795                 case RENDERPATH_GL11:
12796                 case RENDERPATH_GL13:
12797                 case RENDERPATH_GLES1:
12798                         RSurf_ActiveModelEntity(ent, true, false, false);
12799                         break;
12800                 }
12801         }
12802
12803         surfaces = model->data_surfaces;
12804         update = model->brushq1.lightmapupdateflags;
12805
12806         // update light styles
12807         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12808         {
12809                 model_brush_lightstyleinfo_t *style;
12810                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12811                 {
12812                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12813                         {
12814                                 int *list = style->surfacelist;
12815                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12816                                 for (j = 0;j < style->numsurfaces;j++)
12817                                         update[list[j]] = true;
12818                         }
12819                 }
12820         }
12821
12822         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12823
12824         if (debug)
12825         {
12826                 R_DrawDebugModel();
12827                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12828                 return;
12829         }
12830
12831         rsurface.lightmaptexture = NULL;
12832         rsurface.deluxemaptexture = NULL;
12833         rsurface.uselightmaptexture = false;
12834         rsurface.texture = NULL;
12835         rsurface.rtlight = NULL;
12836         numsurfacelist = 0;
12837         // add visible surfaces to draw list
12838         for (i = 0;i < model->nummodelsurfaces;i++)
12839                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12840         // don't do anything if there were no surfaces
12841         if (!numsurfacelist)
12842         {
12843                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12844                 return;
12845         }
12846         // update lightmaps if needed
12847         if (update)
12848         {
12849                 int updated = 0;
12850                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12851                 {
12852                         if (update[j])
12853                         {
12854                                 updated++;
12855                                 R_BuildLightMap(ent, surfaces + j);
12856                         }
12857                 }
12858         }
12859
12860         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12861
12862         // add to stats if desired
12863         if (r_speeds.integer && !skysurfaces && !depthonly)
12864         {
12865                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12866                 for (j = 0;j < numsurfacelist;j++)
12867                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12868         }
12869
12870         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12871 }
12872
12873 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12874 {
12875         static texture_t texture;
12876         static msurface_t surface;
12877         const msurface_t *surfacelist = &surface;
12878
12879         // fake enough texture and surface state to render this geometry
12880
12881         texture.update_lastrenderframe = -1; // regenerate this texture
12882         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12883         texture.basealpha = 1.0f;
12884         texture.currentskinframe = skinframe;
12885         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12886         texture.offsetmapping = OFFSETMAPPING_OFF;
12887         texture.offsetscale = 1;
12888         texture.specularscalemod = 1;
12889         texture.specularpowermod = 1;
12890         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12891         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12892         // JUST GREP FOR "specularscalemod = 1".
12893
12894         surface.texture = &texture;
12895         surface.num_triangles = numtriangles;
12896         surface.num_firsttriangle = firsttriangle;
12897         surface.num_vertices = numvertices;
12898         surface.num_firstvertex = firstvertex;
12899
12900         // now render it
12901         rsurface.texture = R_GetCurrentTexture(surface.texture);
12902         rsurface.lightmaptexture = NULL;
12903         rsurface.deluxemaptexture = NULL;
12904         rsurface.uselightmaptexture = false;
12905         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12906 }
12907
12908 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)
12909 {
12910         static msurface_t surface;
12911         const msurface_t *surfacelist = &surface;
12912
12913         // fake enough texture and surface state to render this geometry
12914         surface.texture = texture;
12915         surface.num_triangles = numtriangles;
12916         surface.num_firsttriangle = firsttriangle;
12917         surface.num_vertices = numvertices;
12918         surface.num_firstvertex = firstvertex;
12919
12920         // now render it
12921         rsurface.texture = R_GetCurrentTexture(surface.texture);
12922         rsurface.lightmaptexture = NULL;
12923         rsurface.deluxemaptexture = NULL;
12924         rsurface.uselightmaptexture = false;
12925         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12926 }