]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Remove r_vertexgeneric_t, r_vertexmesh_t, vid.interleavedarrays and code related...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "cl_collision.h"
30
31 #ifdef WIN32
32 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
37 #ifdef __cplusplus
38 }
39 #endif
40 #endif
41
42 mempool_t *r_main_mempool;
43 rtexturepool_t *r_main_texturepool;
44
45 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
46
47 static qboolean r_loadnormalmap;
48 static qboolean r_loadgloss;
49 qboolean r_loadfog;
50 static qboolean r_loaddds;
51 static qboolean r_savedds;
52 static qboolean r_gpuskeletal;
53
54 //
55 // screen size info
56 //
57 r_refdef_t r_refdef;
58
59 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!"};
60 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!"};
61 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
62 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
63 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)"};
64 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
65 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"};
66 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"};
67 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"};
68 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"};
69 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"};
70 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"};
71
72 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
73 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
74 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
75 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
76 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
77
78 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"};
79 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
80 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
81 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
82 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
83 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
84 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
85 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"};
86 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"};
87 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"};
88 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
89 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
90 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%)" };
91 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)"};
92 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
93 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
94 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"};
95 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
96 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"};
97 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"};
98 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"};
99 cvar_t r_showspriteedges = {0, "r_showspriteedges", "0", "renders a debug outline to show the polygon shape of each sprite frame rendered (may be 2 or more in case of interpolated animations), for debugging rendering bugs with specific view types"};
100 cvar_t r_showparticleedges = {0, "r_showparticleedges", "0", "renders a debug outline to show the polygon shape of each particle, for debugging rendering bugs with specific view types"};
101 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
102 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
103 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
104 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
105 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
106 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
107 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
108 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
109 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)"};
110 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)"};
111 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
112 cvar_t r_cullentities_trace_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
113 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
114 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
115 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"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
119
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
123
124 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
125 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
126 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
127 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
128 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
129
130 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
131 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
132 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
133 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."};
134 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
135 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
136 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
137 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."};
138 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
139 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
140 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
141 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."};
142 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
143 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"};
144 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"};
145 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
146 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
147 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
148 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
149 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
150 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"};
151 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
152 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
153 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
154 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
155 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
156
157 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
158 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
159 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
160 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
161 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
162 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
163 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
164 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
165
166 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)"};
167 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"};
168
169 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
170 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
171 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
172
173 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"};
174 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"};
175 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
176 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"};
177 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
178 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
179 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"};
180 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)"};
181 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)"};
182 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
183
184 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
185 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)"};
186 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
187 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)"};
188 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
189 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)"};
190 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)"};
191 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
192 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"};
193 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."};
194 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203
204 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)"};
205 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)"};
206 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
207 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"};
208 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
209 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
210 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
211 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"};
212 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"};
213
214 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
215 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
216 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
217 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
218
219 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
220 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
221
222 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
223 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
224 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
225 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
226 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
227 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
228
229 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
230 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
231 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
232 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
233 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
234 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
235 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
236 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
237 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
238 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
239
240 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"};
241
242 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"};
243
244 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
245
246 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
247
248 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)"};
249 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)"};
250 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
251 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
252
253 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
254 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"};
255
256 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."};
257
258 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)"};
259 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
260 {
261         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
262         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
263         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
264         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
265 };
266
267 extern cvar_t v_glslgamma_2d;
268
269 extern qboolean v_flipped_state;
270
271 r_framebufferstate_t r_fb;
272
273 /// shadow volume bsp struct with automatically growing nodes buffer
274 svbsp_t r_svbsp;
275
276 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
277
278 rtexture_t *r_texture_blanknormalmap;
279 rtexture_t *r_texture_white;
280 rtexture_t *r_texture_grey128;
281 rtexture_t *r_texture_black;
282 rtexture_t *r_texture_notexture;
283 rtexture_t *r_texture_whitecube;
284 rtexture_t *r_texture_normalizationcube;
285 rtexture_t *r_texture_fogattenuation;
286 rtexture_t *r_texture_fogheighttexture;
287 rtexture_t *r_texture_gammaramps;
288 unsigned int r_texture_gammaramps_serial;
289 //rtexture_t *r_texture_fogintensity;
290 rtexture_t *r_texture_reflectcube;
291
292 // TODO: hash lookups?
293 typedef struct cubemapinfo_s
294 {
295         char basename[64];
296         rtexture_t *texture;
297 }
298 cubemapinfo_t;
299
300 int r_texture_numcubemaps;
301 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
302
303 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
304 unsigned int r_numqueries;
305 unsigned int r_maxqueries;
306
307 typedef struct r_qwskincache_s
308 {
309         char name[MAX_QPATH];
310         skinframe_t *skinframe;
311 }
312 r_qwskincache_t;
313
314 static r_qwskincache_t *r_qwskincache;
315 static int r_qwskincache_size;
316
317 /// vertex coordinates for a quad that covers the screen exactly
318 extern const float r_screenvertex3f[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
327 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
328 {
329         int i;
330         for (i = 0;i < verts;i++)
331         {
332                 out[0] = in[0] * r;
333                 out[1] = in[1] * g;
334                 out[2] = in[2] * b;
335                 out[3] = in[3];
336                 in += 4;
337                 out += 4;
338         }
339 }
340
341 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
342 {
343         int i;
344         for (i = 0;i < verts;i++)
345         {
346                 out[0] = r;
347                 out[1] = g;
348                 out[2] = b;
349                 out[3] = a;
350                 out += 4;
351         }
352 }
353
354 // FIXME: move this to client?
355 void FOG_clear(void)
356 {
357         if (gamemode == GAME_NEHAHRA)
358         {
359                 Cvar_Set("gl_fogenable", "0");
360                 Cvar_Set("gl_fogdensity", "0.2");
361                 Cvar_Set("gl_fogred", "0.3");
362                 Cvar_Set("gl_foggreen", "0.3");
363                 Cvar_Set("gl_fogblue", "0.3");
364         }
365         r_refdef.fog_density = 0;
366         r_refdef.fog_red = 0;
367         r_refdef.fog_green = 0;
368         r_refdef.fog_blue = 0;
369         r_refdef.fog_alpha = 1;
370         r_refdef.fog_start = 0;
371         r_refdef.fog_end = 16384;
372         r_refdef.fog_height = 1<<30;
373         r_refdef.fog_fadedepth = 128;
374         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
375 }
376
377 static void R_BuildBlankTextures(void)
378 {
379         unsigned char data[4];
380         data[2] = 128; // normal X
381         data[1] = 128; // normal Y
382         data[0] = 255; // normal Z
383         data[3] = 255; // height
384         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 255;
386         data[1] = 255;
387         data[2] = 255;
388         data[3] = 255;
389         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 128;
391         data[1] = 128;
392         data[2] = 128;
393         data[3] = 255;
394         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395         data[0] = 0;
396         data[1] = 0;
397         data[2] = 0;
398         data[3] = 255;
399         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
400 }
401
402 static void R_BuildNoTexture(void)
403 {
404         int x, y;
405         unsigned char pix[16][16][4];
406         // this makes a light grey/dark grey checkerboard texture
407         for (y = 0;y < 16;y++)
408         {
409                 for (x = 0;x < 16;x++)
410                 {
411                         if ((y < 8) ^ (x < 8))
412                         {
413                                 pix[y][x][0] = 128;
414                                 pix[y][x][1] = 128;
415                                 pix[y][x][2] = 128;
416                                 pix[y][x][3] = 255;
417                         }
418                         else
419                         {
420                                 pix[y][x][0] = 64;
421                                 pix[y][x][1] = 64;
422                                 pix[y][x][2] = 64;
423                                 pix[y][x][3] = 255;
424                         }
425                 }
426         }
427         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
428 }
429
430 static void R_BuildWhiteCube(void)
431 {
432         unsigned char data[6*1*1*4];
433         memset(data, 255, sizeof(data));
434         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
435 }
436
437 static void R_BuildNormalizationCube(void)
438 {
439         int x, y, side;
440         vec3_t v;
441         vec_t s, t, intensity;
442 #define NORMSIZE 64
443         unsigned char *data;
444         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
445         for (side = 0;side < 6;side++)
446         {
447                 for (y = 0;y < NORMSIZE;y++)
448                 {
449                         for (x = 0;x < NORMSIZE;x++)
450                         {
451                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
452                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
453                                 switch(side)
454                                 {
455                                 default:
456                                 case 0:
457                                         v[0] = 1;
458                                         v[1] = -t;
459                                         v[2] = -s;
460                                         break;
461                                 case 1:
462                                         v[0] = -1;
463                                         v[1] = -t;
464                                         v[2] = s;
465                                         break;
466                                 case 2:
467                                         v[0] = s;
468                                         v[1] = 1;
469                                         v[2] = t;
470                                         break;
471                                 case 3:
472                                         v[0] = s;
473                                         v[1] = -1;
474                                         v[2] = -t;
475                                         break;
476                                 case 4:
477                                         v[0] = s;
478                                         v[1] = -t;
479                                         v[2] = 1;
480                                         break;
481                                 case 5:
482                                         v[0] = -s;
483                                         v[1] = -t;
484                                         v[2] = -1;
485                                         break;
486                                 }
487                                 intensity = 127.0f / sqrt(DotProduct(v, v));
488                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
489                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
490                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
491                                 data[((side*64+y)*64+x)*4+3] = 255;
492                         }
493                 }
494         }
495         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
496         Mem_Free(data);
497 }
498
499 static void R_BuildFogTexture(void)
500 {
501         int x, b;
502 #define FOGWIDTH 256
503         unsigned char data1[FOGWIDTH][4];
504         //unsigned char data2[FOGWIDTH][4];
505         double d, r, alpha;
506
507         r_refdef.fogmasktable_start = r_refdef.fog_start;
508         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
509         r_refdef.fogmasktable_range = r_refdef.fogrange;
510         r_refdef.fogmasktable_density = r_refdef.fog_density;
511
512         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
513         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
514         {
515                 d = (x * r - r_refdef.fogmasktable_start);
516                 if(developer_extra.integer)
517                         Con_DPrintf("%f ", d);
518                 d = max(0, d);
519                 if (r_fog_exp2.integer)
520                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
521                 else
522                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
523                 if(developer_extra.integer)
524                         Con_DPrintf(" : %f ", alpha);
525                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
526                 if(developer_extra.integer)
527                         Con_DPrintf(" = %f\n", alpha);
528                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
529         }
530
531         for (x = 0;x < FOGWIDTH;x++)
532         {
533                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
534                 data1[x][0] = b;
535                 data1[x][1] = b;
536                 data1[x][2] = b;
537                 data1[x][3] = 255;
538                 //data2[x][0] = 255 - b;
539                 //data2[x][1] = 255 - b;
540                 //data2[x][2] = 255 - b;
541                 //data2[x][3] = 255;
542         }
543         if (r_texture_fogattenuation)
544         {
545                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
546                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
547         }
548         else
549         {
550                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
551                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
552         }
553 }
554
555 static void R_BuildFogHeightTexture(void)
556 {
557         unsigned char *inpixels;
558         int size;
559         int x;
560         int y;
561         int j;
562         float c[4];
563         float f;
564         inpixels = NULL;
565         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
566         if (r_refdef.fogheighttexturename[0])
567                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
568         if (!inpixels)
569         {
570                 r_refdef.fog_height_tablesize = 0;
571                 if (r_texture_fogheighttexture)
572                         R_FreeTexture(r_texture_fogheighttexture);
573                 r_texture_fogheighttexture = NULL;
574                 if (r_refdef.fog_height_table2d)
575                         Mem_Free(r_refdef.fog_height_table2d);
576                 r_refdef.fog_height_table2d = NULL;
577                 if (r_refdef.fog_height_table1d)
578                         Mem_Free(r_refdef.fog_height_table1d);
579                 r_refdef.fog_height_table1d = NULL;
580                 return;
581         }
582         size = image_width;
583         r_refdef.fog_height_tablesize = size;
584         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
585         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
586         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
587         Mem_Free(inpixels);
588         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
589         // average fog color table accounting for every fog layer between a point
590         // and the camera.  (Note: attenuation is handled separately!)
591         for (y = 0;y < size;y++)
592         {
593                 for (x = 0;x < size;x++)
594                 {
595                         Vector4Clear(c);
596                         f = 0;
597                         if (x < y)
598                         {
599                                 for (j = x;j <= y;j++)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         else
606                         {
607                                 for (j = x;j >= y;j--)
608                                 {
609                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
610                                         f++;
611                                 }
612                         }
613                         f = 1.0f / f;
614                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
615                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
616                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
617                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
618                 }
619         }
620         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
621 }
622
623 //=======================================================================================================================================================
624
625 static const char *builtinshaderstrings[] =
626 {
627 #include "shader_glsl.h"
628 0
629 };
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *sourcebasename;
643         const char *extension;
644         const char **builtinshaderstrings;
645         const char *pretext;
646         const char *name;
647         char *filename;
648         char *builtinstring;
649         int builtincrc;
650 }
651 shadermodeinfo_t;
652
653 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
654 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
655 {
656         {"#define USEDIFFUSE\n", " diffuse"},
657         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
658         {"#define USEVIEWTINT\n", " viewtint"},
659         {"#define USECOLORMAPPING\n", " colormapping"},
660         {"#define USESATURATION\n", " saturation"},
661         {"#define USEFOGINSIDE\n", " foginside"},
662         {"#define USEFOGOUTSIDE\n", " fogoutside"},
663         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
664         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
665         {"#define USEGAMMARAMPS\n", " gammaramps"},
666         {"#define USECUBEFILTER\n", " cubefilter"},
667         {"#define USEGLOW\n", " glow"},
668         {"#define USEBLOOM\n", " bloom"},
669         {"#define USESPECULAR\n", " specular"},
670         {"#define USEPOSTPROCESSING\n", " postprocessing"},
671         {"#define USEREFLECTION\n", " reflection"},
672         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
673         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
674         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
683         {"#define USETRIPPY\n", " trippy"},
684         {"#define USEDEPTHRGB\n", " depthrgb"},
685         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
686         {"#define USESKELETAL\n", " skeletal"},
687         {"#define USEOCCLUDE\n", " occlude"}
688 };
689
690 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
691 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
692 {
693         // SHADERLANGUAGE_GLSL
694         {
695                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
696                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
697                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
698                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
699                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
700                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
701                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
702                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
703                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
704                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
705                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
712         },
713 };
714
715 struct r_glsl_permutation_s;
716 typedef struct r_glsl_permutation_s
717 {
718         /// hash lookup data
719         struct r_glsl_permutation_s *hashnext;
720         unsigned int mode;
721         dpuint64 permutation;
722
723         /// indicates if we have tried compiling this permutation already
724         qboolean compiled;
725         /// 0 if compilation failed
726         int program;
727         // texture units assigned to each detected uniform
728         int tex_Texture_First;
729         int tex_Texture_Second;
730         int tex_Texture_GammaRamps;
731         int tex_Texture_Normal;
732         int tex_Texture_Color;
733         int tex_Texture_Gloss;
734         int tex_Texture_Glow;
735         int tex_Texture_SecondaryNormal;
736         int tex_Texture_SecondaryColor;
737         int tex_Texture_SecondaryGloss;
738         int tex_Texture_SecondaryGlow;
739         int tex_Texture_Pants;
740         int tex_Texture_Shirt;
741         int tex_Texture_FogHeightTexture;
742         int tex_Texture_FogMask;
743         int tex_Texture_Lightmap;
744         int tex_Texture_Deluxemap;
745         int tex_Texture_Attenuation;
746         int tex_Texture_Cube;
747         int tex_Texture_Refraction;
748         int tex_Texture_Reflection;
749         int tex_Texture_ShadowMap2D;
750         int tex_Texture_CubeProjection;
751         int tex_Texture_ScreenNormalMap;
752         int tex_Texture_ScreenDiffuse;
753         int tex_Texture_ScreenSpecular;
754         int tex_Texture_ReflectMask;
755         int tex_Texture_ReflectCube;
756         int tex_Texture_BounceGrid;
757         /// locations of detected uniforms in program object, or -1 if not found
758         int loc_Texture_First;
759         int loc_Texture_Second;
760         int loc_Texture_GammaRamps;
761         int loc_Texture_Normal;
762         int loc_Texture_Color;
763         int loc_Texture_Gloss;
764         int loc_Texture_Glow;
765         int loc_Texture_SecondaryNormal;
766         int loc_Texture_SecondaryColor;
767         int loc_Texture_SecondaryGloss;
768         int loc_Texture_SecondaryGlow;
769         int loc_Texture_Pants;
770         int loc_Texture_Shirt;
771         int loc_Texture_FogHeightTexture;
772         int loc_Texture_FogMask;
773         int loc_Texture_Lightmap;
774         int loc_Texture_Deluxemap;
775         int loc_Texture_Attenuation;
776         int loc_Texture_Cube;
777         int loc_Texture_Refraction;
778         int loc_Texture_Reflection;
779         int loc_Texture_ShadowMap2D;
780         int loc_Texture_CubeProjection;
781         int loc_Texture_ScreenNormalMap;
782         int loc_Texture_ScreenDiffuse;
783         int loc_Texture_ScreenSpecular;
784         int loc_Texture_ReflectMask;
785         int loc_Texture_ReflectCube;
786         int loc_Texture_BounceGrid;
787         int loc_Alpha;
788         int loc_BloomBlur_Parameters;
789         int loc_ClientTime;
790         int loc_Color_Ambient;
791         int loc_Color_Diffuse;
792         int loc_Color_Specular;
793         int loc_Color_Glow;
794         int loc_Color_Pants;
795         int loc_Color_Shirt;
796         int loc_DeferredColor_Ambient;
797         int loc_DeferredColor_Diffuse;
798         int loc_DeferredColor_Specular;
799         int loc_DeferredMod_Diffuse;
800         int loc_DeferredMod_Specular;
801         int loc_DistortScaleRefractReflect;
802         int loc_EyePosition;
803         int loc_FogColor;
804         int loc_FogHeightFade;
805         int loc_FogPlane;
806         int loc_FogPlaneViewDist;
807         int loc_FogRangeRecip;
808         int loc_LightColor;
809         int loc_LightDir;
810         int loc_LightPosition;
811         int loc_OffsetMapping_ScaleSteps;
812         int loc_OffsetMapping_LodDistance;
813         int loc_OffsetMapping_Bias;
814         int loc_PixelSize;
815         int loc_ReflectColor;
816         int loc_ReflectFactor;
817         int loc_ReflectOffset;
818         int loc_RefractColor;
819         int loc_Saturation;
820         int loc_ScreenCenterRefractReflect;
821         int loc_ScreenScaleRefractReflect;
822         int loc_ScreenToDepth;
823         int loc_ShadowMap_Parameters;
824         int loc_ShadowMap_TextureScale;
825         int loc_SpecularPower;
826         int loc_Skeletal_Transform12;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845         /// uniform block bindings
846         int ubibind_Skeletal_Transform12_UniformBlock;
847         /// uniform block indices
848         int ubiloc_Skeletal_Transform12_UniformBlock;
849 }
850 r_glsl_permutation_t;
851
852 #define SHADERPERMUTATION_HASHSIZE 256
853
854
855 // non-degradable "lightweight" shader parameters to keep the permutations simpler
856 // these can NOT degrade! only use for simple stuff
857 enum
858 {
859         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
860         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
861         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
862         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
863         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
865         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
866         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
867         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
868         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
869         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
870         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
871         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
872         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
873 };
874 #define SHADERSTATICPARMS_COUNT 14
875
876 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
877 static int shaderstaticparms_count = 0;
878
879 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
880 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
881
882 extern qboolean r_shadow_shadowmapsampler;
883 extern int r_shadow_shadowmappcf;
884 qboolean R_CompileShader_CheckStaticParms(void)
885 {
886         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
887         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
888         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
889
890         // detect all
891         if (r_glsl_saturation_redcompensate.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
893         if (r_glsl_vertextextureblend_usebothalphas.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
895         if (r_shadow_glossexact.integer)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
897         if (r_glsl_postprocess.integer)
898         {
899                 if (r_glsl_postprocess_uservec1_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
901                 if (r_glsl_postprocess_uservec2_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
903                 if (r_glsl_postprocess_uservec3_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
905                 if (r_glsl_postprocess_uservec4_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
907         }
908         if (r_fxaa.integer)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
910         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
912
913         if (r_shadow_shadowmapsampler)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
915         if (r_shadow_shadowmappcf > 1)
916                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
917         else if (r_shadow_shadowmappcf)
918                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
919         if (r_celshading.integer)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
921         if (r_celoutlines.integer)
922                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
923
924         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
925 }
926
927 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
928         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
929                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
930         else \
931                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
932 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
933 {
934         shaderstaticparms_count = 0;
935
936         // emit all
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
944         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
945         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
951 }
952
953 /// information about each possible shader permutation
954 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
955 /// currently selected permutation
956 r_glsl_permutation_t *r_glsl_permutation;
957 /// storage for permutations linked in the hash table
958 memexpandablearray_t r_glsl_permutationarray;
959
960 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
961 {
962         //unsigned int hashdepth = 0;
963         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
964         r_glsl_permutation_t *p;
965         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
966         {
967                 if (p->mode == mode && p->permutation == permutation)
968                 {
969                         //if (hashdepth > 10)
970                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
971                         return p;
972                 }
973                 //hashdepth++;
974         }
975         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
976         p->mode = mode;
977         p->permutation = permutation;
978         p->hashnext = r_glsl_permutationhash[mode][hashindex];
979         r_glsl_permutationhash[mode][hashindex] = p;
980         //if (hashdepth > 10)
981         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
982         return p;
983 }
984
985 static char *R_ShaderStrCat(const char **strings)
986 {
987         char *string, *s;
988         const char **p = strings;
989         const char *t;
990         size_t len = 0;
991         for (p = strings;(t = *p);p++)
992                 len += strlen(t);
993         len++;
994         s = string = (char *)Mem_Alloc(r_main_mempool, len);
995         len = 0;
996         for (p = strings;(t = *p);p++)
997         {
998                 len = strlen(t);
999                 memcpy(s, t, len);
1000                 s += len;
1001         }
1002         *s = 0;
1003         return string;
1004 }
1005
1006 static char *R_ShaderStrCat(const char **strings);
1007 static void R_InitShaderModeInfo(void)
1008 {
1009         int i, language;
1010         shadermodeinfo_t *modeinfo;
1011         // 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)
1012         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1013         {
1014                 for (i = 0; i < SHADERMODE_COUNT; i++)
1015                 {
1016                         char filename[MAX_QPATH];
1017                         modeinfo = &shadermodeinfo[language][i];
1018                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1019                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1020                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1021                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1022                 }
1023         }
1024 }
1025
1026 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1027 {
1028         char *shaderstring;
1029         // if the mode has no filename we have to return the builtin string
1030         if (builtinonly || !modeinfo->filename)
1031                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1032         // note that FS_LoadFile appends a 0 byte to make it a valid string
1033         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1034         if (shaderstring)
1035         {
1036                 if (printfromdisknotice)
1037                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1038                 return shaderstring;
1039         }
1040         // fall back to builtinstring
1041         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1042 }
1043
1044 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1045 {
1046         int i;
1047         int ubibind;
1048         int sampler;
1049         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1050         char *sourcestring;
1051         char permutationname[256];
1052         int vertstrings_count = 0;
1053         int geomstrings_count = 0;
1054         int fragstrings_count = 0;
1055         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1056         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1057         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1058
1059         if (p->compiled)
1060                 return;
1061         p->compiled = true;
1062         p->program = 0;
1063
1064         permutationname[0] = 0;
1065         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1066
1067         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1068
1069         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1070         if(vid.support.glshaderversion >= 140)
1071         {
1072                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1073                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1074                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1075                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1076                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1077                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1078         }
1079         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1080         else if(vid.support.glshaderversion >= 130)
1081         {
1082                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1083                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1084                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1085                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1086                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1087                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1088         }
1089         // if we can do #version 120, we should (this adds the invariant keyword)
1090         else if(vid.support.glshaderversion >= 120)
1091         {
1092                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1093                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1094                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1095                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1096                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1097                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1098         }
1099         // GLES also adds several things from GLSL120
1100         switch(vid.renderpath)
1101         {
1102         case RENDERPATH_GLES2:
1103                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1104                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1105                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1106                 break;
1107         default:
1108                 break;
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1ll<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166 #if 0
1167                 // debugging aid
1168                 {
1169                         GLint activeuniformindex = 0;
1170                         GLint numactiveuniforms = 0;
1171                         char uniformname[128];
1172                         GLsizei uniformnamelength = 0;
1173                         GLint uniformsize = 0;
1174                         GLenum uniformtype = 0;
1175                         memset(uniformname, 0, sizeof(uniformname));
1176                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1179                         {
1180                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1182                         }
1183                 }
1184 #endif
1185
1186                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1187                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1188                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1190                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1191                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1192                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1193                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1198                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1199                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1201                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1205                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1206                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1207                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1216                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1218                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1219                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1220                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1221                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1222                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1223                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1224                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1231                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1232                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1233                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1234                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1236                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1237                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1238                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1239                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1243                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1244                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1245                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1246                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1247                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1248                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1251                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1254                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1255                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1256                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1257                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1258                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1259                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1260                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1261                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1262                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272                 // initialize the samplers to refer to the texture units we use
1273                 p->tex_Texture_First = -1;
1274                 p->tex_Texture_Second = -1;
1275                 p->tex_Texture_GammaRamps = -1;
1276                 p->tex_Texture_Normal = -1;
1277                 p->tex_Texture_Color = -1;
1278                 p->tex_Texture_Gloss = -1;
1279                 p->tex_Texture_Glow = -1;
1280                 p->tex_Texture_SecondaryNormal = -1;
1281                 p->tex_Texture_SecondaryColor = -1;
1282                 p->tex_Texture_SecondaryGloss = -1;
1283                 p->tex_Texture_SecondaryGlow = -1;
1284                 p->tex_Texture_Pants = -1;
1285                 p->tex_Texture_Shirt = -1;
1286                 p->tex_Texture_FogHeightTexture = -1;
1287                 p->tex_Texture_FogMask = -1;
1288                 p->tex_Texture_Lightmap = -1;
1289                 p->tex_Texture_Deluxemap = -1;
1290                 p->tex_Texture_Attenuation = -1;
1291                 p->tex_Texture_Cube = -1;
1292                 p->tex_Texture_Refraction = -1;
1293                 p->tex_Texture_Reflection = -1;
1294                 p->tex_Texture_ShadowMap2D = -1;
1295                 p->tex_Texture_CubeProjection = -1;
1296                 p->tex_Texture_ScreenNormalMap = -1;
1297                 p->tex_Texture_ScreenDiffuse = -1;
1298                 p->tex_Texture_ScreenSpecular = -1;
1299                 p->tex_Texture_ReflectMask = -1;
1300                 p->tex_Texture_ReflectCube = -1;
1301                 p->tex_Texture_BounceGrid = -1;
1302                 // bind the texture samplers in use
1303                 sampler = 0;
1304                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1305                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1306                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1307                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1308                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1309                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1310                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1311                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1313                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1314                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1315                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1316                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1317                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1319                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1320                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1321                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1322                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1323                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1324                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1325                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1326                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1327                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1329                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1330                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1331                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1332                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1333                 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335                 if (vid.support.arb_uniform_buffer_object)
1336                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1337                 else
1338 #endif
1339                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340                 // clear the uniform block bindings
1341                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342                 // bind the uniform blocks in use
1343                 ubibind = 0;
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1346 #endif
1347                 // we're done compiling and setting up the shader, at least until it is used
1348                 CHECKGLERROR
1349                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1350         }
1351         else
1352                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1353
1354         // free the strings
1355         if (sourcestring)
1356                 Mem_Free(sourcestring);
1357 }
1358
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1360 {
1361         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362         if (r_glsl_permutation != perm)
1363         {
1364                 r_glsl_permutation = perm;
1365                 if (!r_glsl_permutation->program)
1366                 {
1367                         if (!r_glsl_permutation->compiled)
1368                         {
1369                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1371                         }
1372                         if (!r_glsl_permutation->program)
1373                         {
1374                                 // remove features until we find a valid permutation
1375                                 int i;
1376                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1377                                 {
1378                                         // reduce i more quickly whenever it would not remove any bits
1379                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1380                                         if (!(permutation & j))
1381                                                 continue;
1382                                         permutation -= j;
1383                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384                                         if (!r_glsl_permutation->compiled)
1385                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1386                                         if (r_glsl_permutation->program)
1387                                                 break;
1388                                 }
1389                                 if (i >= SHADERPERMUTATION_COUNT)
1390                                 {
1391                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393                                         qglUseProgram(0);CHECKGLERROR
1394                                         return; // no bit left to clear, entire mode is broken
1395                                 }
1396                         }
1397                 }
1398                 CHECKGLERROR
1399                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1400         }
1401         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1404         CHECKGLERROR
1405 }
1406
1407 void R_GLSL_Restart_f(void)
1408 {
1409         unsigned int i, limit;
1410         switch(vid.renderpath)
1411         {
1412         case RENDERPATH_GL20:
1413         case RENDERPATH_GLES2:
1414                 {
1415                         r_glsl_permutation_t *p;
1416                         r_glsl_permutation = NULL;
1417                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1418                         for (i = 0;i < limit;i++)
1419                         {
1420                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1421                                 {
1422                                         GL_Backend_FreeProgram(p->program);
1423                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1424                                 }
1425                         }
1426                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1427                 }
1428                 break;
1429         }
1430 }
1431
1432 static void R_GLSL_DumpShader_f(void)
1433 {
1434         int i, language, mode, dupe;
1435         char *text;
1436         shadermodeinfo_t *modeinfo;
1437         qfile_t *file;
1438
1439         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1440         {
1441                 modeinfo = shadermodeinfo[language];
1442                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1443                 {
1444                         // don't dump the same file multiple times (most or all shaders come from the same file)
1445                         for (dupe = mode - 1;dupe >= 0;dupe--)
1446                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1447                                         break;
1448                         if (dupe >= 0)
1449                                 continue;
1450                         text = modeinfo[mode].builtinstring;
1451                         if (!text)
1452                                 continue;
1453                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1454                         if (file)
1455                         {
1456                                 FS_Print(file, "/* The engine may define the following macros:\n");
1457                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1458                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1459                                         FS_Print(file, modeinfo[i].pretext);
1460                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1461                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1462                                 FS_Print(file, "*/\n");
1463                                 FS_Print(file, text);
1464                                 FS_Close(file);
1465                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1466                         }
1467                         else
1468                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1469                 }
1470         }
1471 }
1472
1473 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1474 {
1475         dpuint64 permutation = 0;
1476         if (r_trippy.integer && !notrippy)
1477                 permutation |= SHADERPERMUTATION_TRIPPY;
1478         permutation |= SHADERPERMUTATION_VIEWTINT;
1479         if (first)
1480                 permutation |= SHADERPERMUTATION_DIFFUSE;
1481         if (second)
1482                 permutation |= SHADERPERMUTATION_SPECULAR;
1483         if (texturemode == GL_MODULATE)
1484                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1485         else if (texturemode == GL_ADD)
1486                 permutation |= SHADERPERMUTATION_GLOW;
1487         else if (texturemode == GL_DECAL)
1488                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1489         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1490                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1491         if (suppresstexalpha)
1492                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1493         if (!second)
1494                 texturemode = GL_MODULATE;
1495         if (vid.allowalphatocoverage)
1496                 GL_AlphaToCoverage(false);
1497         switch (vid.renderpath)
1498         {
1499         case RENDERPATH_GL20:
1500         case RENDERPATH_GLES2:
1501                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1502                 if (r_glsl_permutation->tex_Texture_First >= 0)
1503                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1504                 if (r_glsl_permutation->tex_Texture_Second >= 0)
1505                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1506                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1507                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1508                 break;
1509         }
1510 }
1511
1512 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1513 {
1514         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1515 }
1516
1517 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1518 {
1519         dpuint64 permutation = 0;
1520         if (r_trippy.integer && !notrippy)
1521                 permutation |= SHADERPERMUTATION_TRIPPY;
1522         if (depthrgb)
1523                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1524         if (skeletal)
1525                 permutation |= SHADERPERMUTATION_SKELETAL;
1526
1527         if (vid.allowalphatocoverage)
1528                 GL_AlphaToCoverage(false);
1529         switch (vid.renderpath)
1530         {
1531         case RENDERPATH_GL20:
1532         case RENDERPATH_GLES2:
1533                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1534 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1535                 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);
1536 #endif
1537                 break;
1538         }
1539 }
1540
1541 #define BLENDFUNC_ALLOWS_COLORMOD      1
1542 #define BLENDFUNC_ALLOWS_FOG           2
1543 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
1544 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1545 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1546 static int R_BlendFuncFlags(int src, int dst)
1547 {
1548         int r = 0;
1549
1550         // a blendfunc allows colormod if:
1551         // a) it can never keep the destination pixel invariant, or
1552         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1553         // this is to prevent unintended side effects from colormod
1554
1555         // a blendfunc allows fog if:
1556         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
1557         // this is to prevent unintended side effects from fog
1558
1559         // these checks are the output of fogeval.pl
1560
1561         r |= BLENDFUNC_ALLOWS_COLORMOD;
1562         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1563         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1564         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1565         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1566         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1567         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1568         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1569         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1570         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
1571         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
1572         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1573         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1574         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1575         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1576         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1577         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1578         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1579         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1580         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1581         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
1582         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1583
1584         return r;
1585 }
1586
1587 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
1588 {
1589         // select a permutation of the lighting shader appropriate to this
1590         // combination of texture, entity, light source, and fogging, only use the
1591         // minimum features necessary to avoid wasting rendering time in the
1592         // fragment shader on features that are not being used
1593         dpuint64 permutation = 0;
1594         unsigned int mode = 0;
1595         int blendfuncflags;
1596         texture_t *t = rsurface.texture;
1597         float m16f[16];
1598         matrix4x4_t tempmatrix;
1599         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
1600         if (r_trippy.integer && !notrippy)
1601                 permutation |= SHADERPERMUTATION_TRIPPY;
1602         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
1603                 permutation |= SHADERPERMUTATION_ALPHAKILL;
1604         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
1605                 permutation |= SHADERPERMUTATION_OCCLUDE;
1606         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
1607                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
1608         if (rsurfacepass == RSURFPASS_BACKGROUND)
1609         {
1610                 // distorted background
1611                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1612                 {
1613                         mode = SHADERMODE_WATER;
1614                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1615                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1616                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
1617                         {
1618                                 // this is the right thing to do for wateralpha
1619                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1620                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1621                         }
1622                         else
1623                         {
1624                                 // this is the right thing to do for entity alpha
1625                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1626                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1627                         }
1628                 }
1629                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
1630                 {
1631                         mode = SHADERMODE_REFRACTION;
1632                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1633                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1634                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1635                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1636                 }
1637                 else
1638                 {
1639                         mode = SHADERMODE_GENERIC;
1640                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
1641                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1642                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1643                 }
1644                 if (vid.allowalphatocoverage)
1645                         GL_AlphaToCoverage(false);
1646         }
1647         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
1648         {
1649                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1650                 {
1651                         switch(t->offsetmapping)
1652                         {
1653                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1654                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1655                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1656                         case OFFSETMAPPING_OFF: break;
1657                         }
1658                 }
1659                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1660                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1661                 // normalmap (deferred prepass), may use alpha test on diffuse
1662                 mode = SHADERMODE_DEFERREDGEOMETRY;
1663                 GL_BlendFunc(GL_ONE, GL_ZERO);
1664                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1665                 if (vid.allowalphatocoverage)
1666                         GL_AlphaToCoverage(false);
1667         }
1668         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1669         {
1670                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1671                 {
1672                         switch(t->offsetmapping)
1673                         {
1674                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1675                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1676                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1677                         case OFFSETMAPPING_OFF: break;
1678                         }
1679                 }
1680                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1682                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1683                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1684                 // light source
1685                 mode = SHADERMODE_LIGHTSOURCE;
1686                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1687                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1688                 if (VectorLength2(rtlightdiffuse) > 0)
1689                         permutation |= SHADERPERMUTATION_DIFFUSE;
1690                 if (VectorLength2(rtlightspecular) > 0)
1691                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1692                 if (r_refdef.fogenabled)
1693                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1694                 if (t->colormapping)
1695                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1696                 if (r_shadow_usingshadowmap2d)
1697                 {
1698                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1699                         if(r_shadow_shadowmapvsdct)
1700                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
1701
1702                         if (r_shadow_shadowmap2ddepthbuffer)
1703                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1704                 }
1705                 if (t->reflectmasktexture)
1706                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1707                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1708                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
1709                 if (vid.allowalphatocoverage)
1710                         GL_AlphaToCoverage(false);
1711         }
1712         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1713         {
1714                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1715                 {
1716                         switch(t->offsetmapping)
1717                         {
1718                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1719                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1720                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1721                         case OFFSETMAPPING_OFF: break;
1722                         }
1723                 }
1724                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1725                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1726                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1727                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1728                 // directional model lighting
1729                 mode = SHADERMODE_LIGHTDIRECTION;
1730                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1731                         permutation |= SHADERPERMUTATION_GLOW;
1732                 if (VectorLength2(t->render_modellight_diffuse))
1733                         permutation |= SHADERPERMUTATION_DIFFUSE;
1734                 if (VectorLength2(t->render_modellight_specular) > 0)
1735                         permutation |= SHADERPERMUTATION_SPECULAR;
1736                 if (r_refdef.fogenabled)
1737                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1738                 if (t->colormapping)
1739                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1740                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1741                 {
1742                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1743                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1744
1745                         if (r_shadow_shadowmap2ddepthbuffer)
1746                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1747                 }
1748                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1749                         permutation |= SHADERPERMUTATION_REFLECTION;
1750                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1751                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1752                 if (t->reflectmasktexture)
1753                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1754                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1755                 {
1756                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1757                         if (r_shadow_bouncegrid_state.directional)
1758                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1759                 }
1760                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1761                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1762                 // when using alphatocoverage, we don't need alphakill
1763                 if (vid.allowalphatocoverage)
1764                 {
1765                         if (r_transparent_alphatocoverage.integer)
1766                         {
1767                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1768                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1769                         }
1770                         else
1771                                 GL_AlphaToCoverage(false);
1772                 }
1773         }
1774         else
1775         {
1776                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1777                 {
1778                         switch(t->offsetmapping)
1779                         {
1780                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1781                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1782                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1783                         case OFFSETMAPPING_OFF: break;
1784                         }
1785                 }
1786                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1787                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1788                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1789                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1790                 // lightmapped wall
1791                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1792                         permutation |= SHADERPERMUTATION_GLOW;
1793                 if (r_refdef.fogenabled)
1794                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1795                 if (t->colormapping)
1796                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1797                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1798                 {
1799                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1800                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1801
1802                         if (r_shadow_shadowmap2ddepthbuffer)
1803                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1804                 }
1805                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1806                         permutation |= SHADERPERMUTATION_REFLECTION;
1807                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1808                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1809                 if (t->reflectmasktexture)
1810                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1811                 if (FAKELIGHT_ENABLED)
1812                 {
1813                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
1814                         mode = SHADERMODE_FAKELIGHT;
1815                         permutation |= SHADERPERMUTATION_DIFFUSE;
1816                         if (VectorLength2(t->render_lightmap_specular) > 0)
1817                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1818                 }
1819                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1820                 {
1821                         // deluxemapping (light direction texture)
1822                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1823                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1824                         else
1825                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1826                         permutation |= SHADERPERMUTATION_DIFFUSE;
1827                         if (VectorLength2(t->render_lightmap_specular) > 0)
1828                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1829                 }
1830                 else if (r_glsl_deluxemapping.integer >= 2)
1831                 {
1832                         // fake deluxemapping (uniform light direction in tangentspace)
1833                         if (rsurface.uselightmaptexture)
1834                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
1835                         else
1836                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
1837                         permutation |= SHADERPERMUTATION_DIFFUSE;
1838                         if (VectorLength2(t->render_lightmap_specular) > 0)
1839                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1840                 }
1841                 else if (rsurface.uselightmaptexture)
1842                 {
1843                         // ordinary lightmapping (q1bsp, q3bsp)
1844                         mode = SHADERMODE_LIGHTMAP;
1845                 }
1846                 else
1847                 {
1848                         // ordinary vertex coloring (q3bsp)
1849                         mode = SHADERMODE_VERTEXCOLOR;
1850                 }
1851                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1852                 {
1853                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1854                         if (r_shadow_bouncegrid_state.directional)
1855                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1856                 }
1857                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1858                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1859                 // when using alphatocoverage, we don't need alphakill
1860                 if (vid.allowalphatocoverage)
1861                 {
1862                         if (r_transparent_alphatocoverage.integer)
1863                         {
1864                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1865                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1866                         }
1867                         else
1868                                 GL_AlphaToCoverage(false);
1869                 }
1870         }
1871         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
1872                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
1873         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1874                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
1875         switch(vid.renderpath)
1876         {
1877         case RENDERPATH_GL20:
1878         case RENDERPATH_GLES2:
1879                 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);
1880                 R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
1881                 R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
1882                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
1883                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
1884                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
1885                 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
1886                 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
1887                 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
1888                 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
1889                 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
1890                 // this has to be after RSurf_PrepareVerticesForBatch
1891                 if (rsurface.batchskeletaltransform3x4buffer)
1892                         permutation |= SHADERPERMUTATION_SKELETAL;
1893                 R_SetupShader_SetPermutationGLSL(mode, permutation);
1894 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1895                 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);
1896 #endif
1897                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
1898                 if (mode == SHADERMODE_LIGHTSOURCE)
1899                 {
1900                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
1901                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1902                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1903                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
1904                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
1905                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
1906         
1907                         // additive passes are only darkened by fog, not tinted
1908                         if (r_glsl_permutation->loc_FogColor >= 0)
1909                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1910                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
1911                 }
1912                 else
1913                 {
1914                         if (mode == SHADERMODE_FLATCOLOR)
1915                         {
1916                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
1917                         }
1918                         else if (mode == SHADERMODE_LIGHTDIRECTION)
1919                         {
1920                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
1921                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
1922                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
1923                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
1924                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
1925                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1926                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
1927                         }
1928                         else
1929                         {
1930                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
1931                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
1932                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
1933                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
1934                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
1935                         }
1936                         // additive passes are only darkened by fog, not tinted
1937                         if (r_glsl_permutation->loc_FogColor >= 0)
1938                         {
1939                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
1940                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1941                                 else
1942                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1943                         }
1944                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
1945                         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]);
1946                         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]);
1947                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
1948                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
1949                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
1950                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
1951                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
1952                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
1953                 }
1954                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
1955                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
1956                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
1957                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
1958                 {
1959                         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]);
1960                         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]);
1961                 }
1962                 else
1963                 {
1964                         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]);
1965                         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]);
1966                 }
1967
1968                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
1969                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
1970                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
1971                 if (r_glsl_permutation->loc_Color_Pants >= 0)
1972                 {
1973                         if (t->pantstexture)
1974                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
1975                         else
1976                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1977                 }
1978                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1979                 {
1980                         if (t->shirttexture)
1981                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
1982                         else
1983                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1984                 }
1985                 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]);
1986                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
1987                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
1988                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
1989                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
1990                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
1991                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1992                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1993                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
1994                         );
1995                 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);
1996                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
1997                 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]);
1998                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
1999                 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);}
2000                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2001
2002                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2003                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2004                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2005                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2006                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2007                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2008                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2009                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2010                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2011                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2012                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2013                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2014                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2015                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2016                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2017                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2018                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2019                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2020                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2021                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2022                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2023                 {
2024                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2025                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2026                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2027                 }
2028                 else
2029                 {
2030                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2031                 }
2032                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2033                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2034                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2035                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2036                 {
2037                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2038                         if (rsurface.rtlight)
2039                         {
2040                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2041                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2042                         }
2043                 }
2044                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2045                 CHECKGLERROR
2046                 break;
2047         }
2048 }
2049
2050 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2051 {
2052         // select a permutation of the lighting shader appropriate to this
2053         // combination of texture, entity, light source, and fogging, only use the
2054         // minimum features necessary to avoid wasting rendering time in the
2055         // fragment shader on features that are not being used
2056         dpuint64 permutation = 0;
2057         unsigned int mode = 0;
2058         const float *lightcolorbase = rtlight->currentcolor;
2059         float ambientscale = rtlight->ambientscale;
2060         float diffusescale = rtlight->diffusescale;
2061         float specularscale = rtlight->specularscale;
2062         // this is the location of the light in view space
2063         vec3_t viewlightorigin;
2064         // this transforms from view space (camera) to light space (cubemap)
2065         matrix4x4_t viewtolight;
2066         matrix4x4_t lighttoview;
2067         float viewtolight16f[16];
2068         // light source
2069         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2070         if (rtlight->currentcubemap != r_texture_whitecube)
2071                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2072         if (diffusescale > 0)
2073                 permutation |= SHADERPERMUTATION_DIFFUSE;
2074         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2075                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2076         if (r_shadow_usingshadowmap2d)
2077         {
2078                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2079                 if (r_shadow_shadowmapvsdct)
2080                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2081
2082                 if (r_shadow_shadowmap2ddepthbuffer)
2083                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2084         }
2085         if (vid.allowalphatocoverage)
2086                 GL_AlphaToCoverage(false);
2087         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2088         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2089         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2090         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2091         switch(vid.renderpath)
2092         {
2093         case RENDERPATH_GL20:
2094         case RENDERPATH_GLES2:
2095                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2096                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2097                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2098                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
2099                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
2100                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
2101                 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]);
2102                 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]);
2103                 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);
2104                 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]);
2105                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2106
2107                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2108                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2109                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2110                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
2111                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2112                 break;
2113         }
2114 }
2115
2116 #define SKINFRAME_HASH 1024
2117
2118 typedef struct
2119 {
2120         unsigned int loadsequence; // incremented each level change
2121         memexpandablearray_t array;
2122         skinframe_t *hash[SKINFRAME_HASH];
2123 }
2124 r_skinframe_t;
2125 r_skinframe_t r_skinframe;
2126
2127 void R_SkinFrame_PrepareForPurge(void)
2128 {
2129         r_skinframe.loadsequence++;
2130         // wrap it without hitting zero
2131         if (r_skinframe.loadsequence >= 200)
2132                 r_skinframe.loadsequence = 1;
2133 }
2134
2135 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2136 {
2137         if (!skinframe)
2138                 return;
2139         // mark the skinframe as used for the purging code
2140         skinframe->loadsequence = r_skinframe.loadsequence;
2141 }
2142
2143 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
2144 {
2145         if (s == NULL)
2146                 return;
2147         if (s->merged == s->base)
2148                 s->merged = NULL;
2149         R_PurgeTexture(s->stain); s->stain = NULL;
2150         R_PurgeTexture(s->merged); s->merged = NULL;
2151         R_PurgeTexture(s->base); s->base = NULL;
2152         R_PurgeTexture(s->pants); s->pants = NULL;
2153         R_PurgeTexture(s->shirt); s->shirt = NULL;
2154         R_PurgeTexture(s->nmap); s->nmap = NULL;
2155         R_PurgeTexture(s->gloss); s->gloss = NULL;
2156         R_PurgeTexture(s->glow); s->glow = NULL;
2157         R_PurgeTexture(s->fog); s->fog = NULL;
2158         R_PurgeTexture(s->reflect); s->reflect = NULL;
2159         s->loadsequence = 0;
2160 }
2161
2162 void R_SkinFrame_Purge(void)
2163 {
2164         int i;
2165         skinframe_t *s;
2166         for (i = 0;i < SKINFRAME_HASH;i++)
2167         {
2168                 for (s = r_skinframe.hash[i];s;s = s->next)
2169                 {
2170                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2171                                 R_SkinFrame_PurgeSkinFrame(s);
2172                 }
2173         }
2174 }
2175
2176 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2177         skinframe_t *item;
2178         char basename[MAX_QPATH];
2179
2180         Image_StripImageExtension(name, basename, sizeof(basename));
2181
2182         if( last == NULL ) {
2183                 int hashindex;
2184                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2185                 item = r_skinframe.hash[hashindex];
2186         } else {
2187                 item = last->next;
2188         }
2189
2190         // linearly search through the hash bucket
2191         for( ; item ; item = item->next ) {
2192                 if( !strcmp( item->basename, basename ) ) {
2193                         return item;
2194                 }
2195         }
2196         return NULL;
2197 }
2198
2199 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2200 {
2201         skinframe_t *item;
2202         int hashindex;
2203         char basename[MAX_QPATH];
2204
2205         Image_StripImageExtension(name, basename, sizeof(basename));
2206
2207         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2208         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2209                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
2210                         break;
2211
2212         if (!item)
2213         {
2214                 if (!add)
2215                         return NULL;
2216                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2217                 memset(item, 0, sizeof(*item));
2218                 strlcpy(item->basename, basename, sizeof(item->basename));
2219                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
2220                 item->comparewidth = comparewidth;
2221                 item->compareheight = compareheight;
2222                 item->comparecrc = comparecrc;
2223                 item->next = r_skinframe.hash[hashindex];
2224                 r_skinframe.hash[hashindex] = item;
2225         }
2226         else if (textureflags & TEXF_FORCE_RELOAD)
2227         {
2228                 if (!add)
2229                         return NULL;
2230                 R_SkinFrame_PurgeSkinFrame(item);
2231         }
2232
2233         R_SkinFrame_MarkUsed(item);
2234         return item;
2235 }
2236
2237 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2238         { \
2239                 unsigned long long avgcolor[5], wsum; \
2240                 int pix, comp, w; \
2241                 avgcolor[0] = 0; \
2242                 avgcolor[1] = 0; \
2243                 avgcolor[2] = 0; \
2244                 avgcolor[3] = 0; \
2245                 avgcolor[4] = 0; \
2246                 wsum = 0; \
2247                 for(pix = 0; pix < cnt; ++pix) \
2248                 { \
2249                         w = 0; \
2250                         for(comp = 0; comp < 3; ++comp) \
2251                                 w += getpixel; \
2252                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2253                         { \
2254                                 ++wsum; \
2255                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2256                                 w = getpixel; \
2257                                 for(comp = 0; comp < 3; ++comp) \
2258                                         avgcolor[comp] += getpixel * w; \
2259                                 avgcolor[3] += w; \
2260                         } \
2261                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2262                         avgcolor[4] += getpixel; \
2263                 } \
2264                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2265                         avgcolor[3] = 1; \
2266                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2267                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2268                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2269                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2270         }
2271
2272 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2273 {
2274         skinframe_t *skinframe;
2275
2276         if (cls.state == ca_dedicated)
2277                 return NULL;
2278
2279         // return an existing skinframe if already loaded
2280         // if loading of the first image fails, don't make a new skinframe as it
2281         // would cause all future lookups of this to be missing
2282         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, -1, false);
2283         if (skinframe && skinframe->base)
2284                 return skinframe;
2285
2286         return R_SkinFrame_LoadExternal_SkinFrame(skinframe, name, textureflags, complain, fallbacknotexture);
2287 }
2288
2289 extern cvar_t gl_picmip;
2290 skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2291 {
2292         int j;
2293         unsigned char *pixels;
2294         unsigned char *bumppixels;
2295         unsigned char *basepixels = NULL;
2296         int basepixels_width = 0;
2297         int basepixels_height = 0;
2298         rtexture_t *ddsbase = NULL;
2299         qboolean ddshasalpha = false;
2300         float ddsavgcolor[4];
2301         char basename[MAX_QPATH];
2302         int miplevel = R_PicmipForFlags(textureflags);
2303         int savemiplevel = miplevel;
2304         int mymiplevel;
2305         char vabuf[1024];
2306
2307         if (cls.state == ca_dedicated)
2308                 return NULL;
2309
2310         Image_StripImageExtension(name, basename, sizeof(basename));
2311
2312         // check for DDS texture file first
2313         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
2314         {
2315                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
2316                 if (basepixels == NULL && fallbacknotexture)
2317                         basepixels = Image_GenerateNoTexture();
2318                 if (basepixels == NULL)
2319                         return NULL;
2320         }
2321
2322         // FIXME handle miplevel
2323
2324         if (developer_loading.integer)
2325                 Con_Printf("loading skin \"%s\"\n", name);
2326
2327         // we've got some pixels to store, so really allocate this new texture now
2328         if (!skinframe)
2329                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2330         textureflags &= ~TEXF_FORCE_RELOAD;
2331         skinframe->stain = NULL;
2332         skinframe->merged = NULL;
2333         skinframe->base = NULL;
2334         skinframe->pants = NULL;
2335         skinframe->shirt = NULL;
2336         skinframe->nmap = NULL;
2337         skinframe->gloss = NULL;
2338         skinframe->glow = NULL;
2339         skinframe->fog = NULL;
2340         skinframe->reflect = NULL;
2341         skinframe->hasalpha = false;
2342         // we could store the q2animname here too
2343
2344         if (ddsbase)
2345         {
2346                 skinframe->base = ddsbase;
2347                 skinframe->hasalpha = ddshasalpha;
2348                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
2349                 if (r_loadfog && skinframe->hasalpha)
2350                         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);
2351                 //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]);
2352         }
2353         else
2354         {
2355                 basepixels_width = image_width;
2356                 basepixels_height = image_height;
2357                 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);
2358                 if (textureflags & TEXF_ALPHA)
2359                 {
2360                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2361                         {
2362                                 if (basepixels[j] < 255)
2363                                 {
2364                                         skinframe->hasalpha = true;
2365                                         break;
2366                                 }
2367                         }
2368                         if (r_loadfog && skinframe->hasalpha)
2369                         {
2370                                 // has transparent pixels
2371                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2372                                 for (j = 0;j < image_width * image_height * 4;j += 4)
2373                                 {
2374                                         pixels[j+0] = 255;
2375                                         pixels[j+1] = 255;
2376                                         pixels[j+2] = 255;
2377                                         pixels[j+3] = basepixels[j+3];
2378                                 }
2379                                 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);
2380                                 Mem_Free(pixels);
2381                         }
2382                 }
2383                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2384 #ifndef USE_GLES2
2385                 //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]);
2386                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
2387                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
2388                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
2389                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2390 #endif
2391         }
2392
2393         if (r_loaddds)
2394         {
2395                 mymiplevel = savemiplevel;
2396                 if (r_loadnormalmap)
2397                         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);
2398                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2399                 if (r_loadgloss)
2400                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2401                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2402                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2403                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2404         }
2405
2406         // _norm is the name used by tenebrae and has been adopted as standard
2407         if (r_loadnormalmap && skinframe->nmap == NULL)
2408         {
2409                 mymiplevel = savemiplevel;
2410                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2411                 {
2412                         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);
2413                         Mem_Free(pixels);
2414                         pixels = NULL;
2415                 }
2416                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2417                 {
2418                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2419                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2420                         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);
2421                         Mem_Free(pixels);
2422                         Mem_Free(bumppixels);
2423                 }
2424                 else if (r_shadow_bumpscale_basetexture.value > 0)
2425                 {
2426                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2427                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2428                         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);
2429                         Mem_Free(pixels);
2430                 }
2431 #ifndef USE_GLES2
2432                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
2433                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2434 #endif
2435         }
2436
2437         // _luma is supported only for tenebrae compatibility
2438         // _glow is the preferred name
2439         mymiplevel = savemiplevel;
2440         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))))
2441         {
2442                 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);
2443 #ifndef USE_GLES2
2444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
2445                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2446 #endif
2447                 Mem_Free(pixels);pixels = NULL;
2448         }
2449
2450         mymiplevel = savemiplevel;
2451         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
2452         {
2453                 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);
2454 #ifndef USE_GLES2
2455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
2456                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2457 #endif
2458                 Mem_Free(pixels);
2459                 pixels = NULL;
2460         }
2461
2462         mymiplevel = savemiplevel;
2463         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
2464         {
2465                 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);
2466 #ifndef USE_GLES2
2467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
2468                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2469 #endif
2470                 Mem_Free(pixels);
2471                 pixels = NULL;
2472         }
2473
2474         mymiplevel = savemiplevel;
2475         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
2476         {
2477                 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);
2478 #ifndef USE_GLES2
2479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
2480                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2481 #endif
2482                 Mem_Free(pixels);
2483                 pixels = NULL;
2484         }
2485
2486         mymiplevel = savemiplevel;
2487         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
2488         {
2489                 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);
2490 #ifndef USE_GLES2
2491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
2492                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2493 #endif
2494                 Mem_Free(pixels);
2495                 pixels = NULL;
2496         }
2497
2498         if (basepixels)
2499                 Mem_Free(basepixels);
2500
2501         return skinframe;
2502 }
2503
2504 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2505 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
2506 {
2507         int i;
2508         skinframe_t *skinframe;
2509         char vabuf[1024];
2510
2511         if (cls.state == ca_dedicated)
2512                 return NULL;
2513
2514         // if already loaded just return it, otherwise make a new skinframe
2515         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (!(textureflags & TEXF_FORCE_RELOAD) && skindata) ? CRC_Block(skindata, width*height*4) : -1, true);
2516         if (skinframe->base)
2517                 return skinframe;
2518         textureflags &= ~TEXF_FORCE_RELOAD;
2519
2520         skinframe->stain = NULL;
2521         skinframe->merged = NULL;
2522         skinframe->base = NULL;
2523         skinframe->pants = NULL;
2524         skinframe->shirt = NULL;
2525         skinframe->nmap = NULL;
2526         skinframe->gloss = NULL;
2527         skinframe->glow = NULL;
2528         skinframe->fog = NULL;
2529         skinframe->reflect = NULL;
2530         skinframe->hasalpha = false;
2531
2532         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2533         if (!skindata)
2534                 return NULL;
2535
2536         if (developer_loading.integer)
2537                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2538
2539         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2540         {
2541                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2542                 unsigned char *b = a + width * height * 4;
2543                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2544                 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);
2545                 Mem_Free(a);
2546         }
2547         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
2548         if (textureflags & TEXF_ALPHA)
2549         {
2550                 for (i = 3;i < width * height * 4;i += 4)
2551                 {
2552                         if (skindata[i] < 255)
2553                         {
2554                                 skinframe->hasalpha = true;
2555                                 break;
2556                         }
2557                 }
2558                 if (r_loadfog && skinframe->hasalpha)
2559                 {
2560                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2561                         memcpy(fogpixels, skindata, width * height * 4);
2562                         for (i = 0;i < width * height * 4;i += 4)
2563                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2564                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
2565                         Mem_Free(fogpixels);
2566                 }
2567         }
2568
2569         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2570         //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]);
2571
2572         return skinframe;
2573 }
2574
2575 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2576 {
2577         int i;
2578         int featuresmask;
2579         skinframe_t *skinframe;
2580
2581         if (cls.state == ca_dedicated)
2582                 return NULL;
2583
2584         // if already loaded just return it, otherwise make a new skinframe
2585         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (!(textureflags & TEXF_FORCE_RELOAD) && skindata) ? CRC_Block(skindata, width*height) : -1, true);
2586         if (skinframe->base)
2587                 return skinframe;
2588         //textureflags &= ~TEXF_FORCE_RELOAD;
2589
2590         skinframe->stain = NULL;
2591         skinframe->merged = NULL;
2592         skinframe->base = NULL;
2593         skinframe->pants = NULL;
2594         skinframe->shirt = NULL;
2595         skinframe->nmap = NULL;
2596         skinframe->gloss = NULL;
2597         skinframe->glow = NULL;
2598         skinframe->fog = NULL;
2599         skinframe->reflect = NULL;
2600         skinframe->hasalpha = false;
2601
2602         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2603         if (!skindata)
2604                 return NULL;
2605
2606         if (developer_loading.integer)
2607                 Con_Printf("loading quake skin \"%s\"\n", name);
2608
2609         // 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)
2610         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
2611         memcpy(skinframe->qpixels, skindata, width*height);
2612         skinframe->qwidth = width;
2613         skinframe->qheight = height;
2614
2615         featuresmask = 0;
2616         for (i = 0;i < width * height;i++)
2617                 featuresmask |= palette_featureflags[skindata[i]];
2618
2619         skinframe->hasalpha = false;
2620         // fence textures
2621         if (name[0] == '{')
2622                 skinframe->hasalpha = true;
2623         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2624         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2625         skinframe->qgeneratemerged = true;
2626         skinframe->qgeneratebase = skinframe->qhascolormapping;
2627         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2628
2629         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2630         //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]);
2631
2632         return skinframe;
2633 }
2634
2635 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2636 {
2637         int width;
2638         int height;
2639         unsigned char *skindata;
2640         char vabuf[1024];
2641
2642         if (!skinframe->qpixels)
2643                 return;
2644
2645         if (!skinframe->qhascolormapping)
2646                 colormapped = false;
2647
2648         if (colormapped)
2649         {
2650                 if (!skinframe->qgeneratebase)
2651                         return;
2652         }
2653         else
2654         {
2655                 if (!skinframe->qgeneratemerged)
2656                         return;
2657         }
2658
2659         width = skinframe->qwidth;
2660         height = skinframe->qheight;
2661         skindata = skinframe->qpixels;
2662
2663         if (skinframe->qgeneratenmap)
2664         {
2665                 unsigned char *a, *b;
2666                 skinframe->qgeneratenmap = false;
2667                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2668                 b = a + width * height * 4;
2669                 // use either a custom palette or the quake palette
2670                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
2671                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2672                 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);
2673                 Mem_Free(a);
2674         }
2675
2676         if (skinframe->qgenerateglow)
2677         {
2678                 skinframe->qgenerateglow = false;
2679                 if (skinframe->hasalpha) // fence textures
2680                         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
2681                 else
2682                         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
2683         }
2684
2685         if (colormapped)
2686         {
2687                 skinframe->qgeneratebase = false;
2688                 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);
2689                 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);
2690                 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);
2691         }
2692         else
2693         {
2694                 skinframe->qgeneratemerged = false;
2695                 if (skinframe->hasalpha) // fence textures
2696                         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);
2697                 else
2698                         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);
2699         }
2700
2701         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2702         {
2703                 Mem_Free(skinframe->qpixels);
2704                 skinframe->qpixels = NULL;
2705         }
2706 }
2707
2708 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)
2709 {
2710         int i;
2711         skinframe_t *skinframe;
2712         char vabuf[1024];
2713
2714         if (cls.state == ca_dedicated)
2715                 return NULL;
2716
2717         // if already loaded just return it, otherwise make a new skinframe
2718         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2719         if (skinframe->base)
2720                 return skinframe;
2721         textureflags &= ~TEXF_FORCE_RELOAD;
2722
2723         skinframe->stain = NULL;
2724         skinframe->merged = NULL;
2725         skinframe->base = NULL;
2726         skinframe->pants = NULL;
2727         skinframe->shirt = NULL;
2728         skinframe->nmap = NULL;
2729         skinframe->gloss = NULL;
2730         skinframe->glow = NULL;
2731         skinframe->fog = NULL;
2732         skinframe->reflect = NULL;
2733         skinframe->hasalpha = false;
2734
2735         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2736         if (!skindata)
2737                 return NULL;
2738
2739         if (developer_loading.integer)
2740                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2741
2742         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
2743         if ((textureflags & TEXF_ALPHA) && alphapalette)
2744         {
2745                 for (i = 0;i < width * height;i++)
2746                 {
2747                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2748                         {
2749                                 skinframe->hasalpha = true;
2750                                 break;
2751                         }
2752                 }
2753                 if (r_loadfog && skinframe->hasalpha)
2754                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
2755         }
2756
2757         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2758         //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]);
2759
2760         return skinframe;
2761 }
2762
2763 skinframe_t *R_SkinFrame_LoadMissing(void)
2764 {
2765         skinframe_t *skinframe;
2766
2767         if (cls.state == ca_dedicated)
2768                 return NULL;
2769
2770         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
2771         skinframe->stain = NULL;
2772         skinframe->merged = NULL;
2773         skinframe->base = NULL;
2774         skinframe->pants = NULL;
2775         skinframe->shirt = NULL;
2776         skinframe->nmap = NULL;
2777         skinframe->gloss = NULL;
2778         skinframe->glow = NULL;
2779         skinframe->fog = NULL;
2780         skinframe->reflect = NULL;
2781         skinframe->hasalpha = false;
2782
2783         skinframe->avgcolor[0] = rand() / RAND_MAX;
2784         skinframe->avgcolor[1] = rand() / RAND_MAX;
2785         skinframe->avgcolor[2] = rand() / RAND_MAX;
2786         skinframe->avgcolor[3] = 1;
2787
2788         return skinframe;
2789 }
2790
2791 skinframe_t *R_SkinFrame_LoadNoTexture(void)
2792 {
2793         int x, y;
2794         static unsigned char pix[16][16][4];
2795
2796         if (cls.state == ca_dedicated)
2797                 return NULL;
2798
2799         // this makes a light grey/dark grey checkerboard texture
2800         if (!pix[0][0][3])
2801         {
2802                 for (y = 0; y < 16; y++)
2803                 {
2804                         for (x = 0; x < 16; x++)
2805                         {
2806                                 if ((y < 8) ^ (x < 8))
2807                                 {
2808                                         pix[y][x][0] = 128;
2809                                         pix[y][x][1] = 128;
2810                                         pix[y][x][2] = 128;
2811                                         pix[y][x][3] = 255;
2812                                 }
2813                                 else
2814                                 {
2815                                         pix[y][x][0] = 64;
2816                                         pix[y][x][1] = 64;
2817                                         pix[y][x][2] = 64;
2818                                         pix[y][x][3] = 255;
2819                                 }
2820                         }
2821                 }
2822         }
2823
2824         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
2825 }
2826
2827 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
2828 {
2829         skinframe_t *skinframe;
2830         if (cls.state == ca_dedicated)
2831                 return NULL;
2832         // if already loaded just return it, otherwise make a new skinframe
2833         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
2834         if (skinframe->base)
2835                 return skinframe;
2836         textureflags &= ~TEXF_FORCE_RELOAD;
2837         skinframe->stain = NULL;
2838         skinframe->merged = NULL;
2839         skinframe->base = NULL;
2840         skinframe->pants = NULL;
2841         skinframe->shirt = NULL;
2842         skinframe->nmap = NULL;
2843         skinframe->gloss = NULL;
2844         skinframe->glow = NULL;
2845         skinframe->fog = NULL;
2846         skinframe->reflect = NULL;
2847         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
2848         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2849         if (!tex)
2850                 return NULL;
2851         if (developer_loading.integer)
2852                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2853         skinframe->base = skinframe->merged = tex;
2854         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
2855         return skinframe;
2856 }
2857
2858 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
2859 typedef struct suffixinfo_s
2860 {
2861         const char *suffix;
2862         qboolean flipx, flipy, flipdiagonal;
2863 }
2864 suffixinfo_t;
2865 static suffixinfo_t suffix[3][6] =
2866 {
2867         {
2868                 {"px",   false, false, false},
2869                 {"nx",   false, false, false},
2870                 {"py",   false, false, false},
2871                 {"ny",   false, false, false},
2872                 {"pz",   false, false, false},
2873                 {"nz",   false, false, false}
2874         },
2875         {
2876                 {"posx", false, false, false},
2877                 {"negx", false, false, false},
2878                 {"posy", false, false, false},
2879                 {"negy", false, false, false},
2880                 {"posz", false, false, false},
2881                 {"negz", false, false, false}
2882         },
2883         {
2884                 {"rt",    true, false,  true},
2885                 {"lf",   false,  true,  true},
2886                 {"ft",    true,  true, false},
2887                 {"bk",   false, false, false},
2888                 {"up",    true, false,  true},
2889                 {"dn",    true, false,  true}
2890         }
2891 };
2892
2893 static int componentorder[4] = {0, 1, 2, 3};
2894
2895 static rtexture_t *R_LoadCubemap(const char *basename)
2896 {
2897         int i, j, cubemapsize;
2898         unsigned char *cubemappixels, *image_buffer;
2899         rtexture_t *cubemaptexture;
2900         char name[256];
2901         // must start 0 so the first loadimagepixels has no requested width/height
2902         cubemapsize = 0;
2903         cubemappixels = NULL;
2904         cubemaptexture = NULL;
2905         // keep trying different suffix groups (posx, px, rt) until one loads
2906         for (j = 0;j < 3 && !cubemappixels;j++)
2907         {
2908                 // load the 6 images in the suffix group
2909                 for (i = 0;i < 6;i++)
2910                 {
2911                         // generate an image name based on the base and and suffix
2912                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
2913                         // load it
2914                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
2915                         {
2916                                 // an image loaded, make sure width and height are equal
2917                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
2918                                 {
2919                                         // if this is the first image to load successfully, allocate the cubemap memory
2920                                         if (!cubemappixels && image_width >= 1)
2921                                         {
2922                                                 cubemapsize = image_width;
2923                                                 // note this clears to black, so unavailable sides are black
2924                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
2925                                         }
2926                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
2927                                         if (cubemappixels)
2928                                                 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);
2929                                 }
2930                                 else
2931                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
2932                                 // free the image
2933                                 Mem_Free(image_buffer);
2934                         }
2935                 }
2936         }
2937         // if a cubemap loaded, upload it
2938         if (cubemappixels)
2939         {
2940                 if (developer_loading.integer)
2941                         Con_Printf("loading cubemap \"%s\"\n", basename);
2942
2943                 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);
2944                 Mem_Free(cubemappixels);
2945         }
2946         else
2947         {
2948                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
2949                 if (developer_loading.integer)
2950                 {
2951                         Con_Printf("(tried tried images ");
2952                         for (j = 0;j < 3;j++)
2953                                 for (i = 0;i < 6;i++)
2954                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
2955                         Con_Print(" and was unable to find any of them).\n");
2956                 }
2957         }
2958         return cubemaptexture;
2959 }
2960
2961 rtexture_t *R_GetCubemap(const char *basename)
2962 {
2963         int i;
2964         for (i = 0;i < r_texture_numcubemaps;i++)
2965                 if (r_texture_cubemaps[i] != NULL)
2966                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
2967                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
2968         if (i >= MAX_CUBEMAPS || !r_main_mempool)
2969                 return r_texture_whitecube;
2970         r_texture_numcubemaps++;
2971         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
2972         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
2973         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
2974         return r_texture_cubemaps[i]->texture;
2975 }
2976
2977 static void R_Main_FreeViewCache(void)
2978 {
2979         if (r_refdef.viewcache.entityvisible)
2980                 Mem_Free(r_refdef.viewcache.entityvisible);
2981         if (r_refdef.viewcache.world_pvsbits)
2982                 Mem_Free(r_refdef.viewcache.world_pvsbits);
2983         if (r_refdef.viewcache.world_leafvisible)
2984                 Mem_Free(r_refdef.viewcache.world_leafvisible);
2985         if (r_refdef.viewcache.world_surfacevisible)
2986                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2987         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2988 }
2989
2990 static void R_Main_ResizeViewCache(void)
2991 {
2992         int numentities = r_refdef.scene.numentities;
2993         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2994         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2995         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2996         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2997         if (r_refdef.viewcache.maxentities < numentities)
2998         {
2999                 r_refdef.viewcache.maxentities = numentities;
3000                 if (r_refdef.viewcache.entityvisible)
3001                         Mem_Free(r_refdef.viewcache.entityvisible);
3002                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3003         }
3004         if (r_refdef.viewcache.world_numclusters != numclusters)
3005         {
3006                 r_refdef.viewcache.world_numclusters = numclusters;
3007                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3008                 if (r_refdef.viewcache.world_pvsbits)
3009                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3010                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3011         }
3012         if (r_refdef.viewcache.world_numleafs != numleafs)
3013         {
3014                 r_refdef.viewcache.world_numleafs = numleafs;
3015                 if (r_refdef.viewcache.world_leafvisible)
3016                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3017                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3018         }
3019         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3020         {
3021                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3022                 if (r_refdef.viewcache.world_surfacevisible)
3023                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3024                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3025         }
3026 }
3027
3028 extern rtexture_t *loadingscreentexture;
3029 static void gl_main_start(void)
3030 {
3031         loadingscreentexture = NULL;
3032         r_texture_blanknormalmap = NULL;
3033         r_texture_white = NULL;
3034         r_texture_grey128 = NULL;
3035         r_texture_black = NULL;
3036         r_texture_whitecube = NULL;
3037         r_texture_normalizationcube = NULL;
3038         r_texture_fogattenuation = NULL;
3039         r_texture_fogheighttexture = NULL;
3040         r_texture_gammaramps = NULL;
3041         r_texture_numcubemaps = 0;
3042         r_uniformbufferalignment = 32;
3043
3044         r_loaddds = r_texture_dds_load.integer != 0;
3045         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3046
3047         switch(vid.renderpath)
3048         {
3049         case RENDERPATH_GL20:
3050         case RENDERPATH_GLES2:
3051                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3052                 Cvar_SetValueQuick(&gl_combine, 1);
3053                 Cvar_SetValueQuick(&r_glsl, 1);
3054                 r_loadnormalmap = true;
3055                 r_loadgloss = true;
3056                 r_loadfog = false;
3057 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3058                 if (vid.support.arb_uniform_buffer_object)
3059                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3060 #endif
3061                         break;
3062         }
3063
3064         R_AnimCache_Free();
3065         R_FrameData_Reset();
3066         R_BufferData_Reset();
3067
3068         r_numqueries = 0;
3069         r_maxqueries = 0;
3070         memset(r_queries, 0, sizeof(r_queries));
3071
3072         r_qwskincache = NULL;
3073         r_qwskincache_size = 0;
3074
3075         // due to caching of texture_t references, the collision cache must be reset
3076         Collision_Cache_Reset(true);
3077
3078         // set up r_skinframe loading system for textures
3079         memset(&r_skinframe, 0, sizeof(r_skinframe));
3080         r_skinframe.loadsequence = 1;
3081         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3082
3083         r_main_texturepool = R_AllocTexturePool();
3084         R_BuildBlankTextures();
3085         R_BuildNoTexture();
3086         if (vid.support.arb_texture_cube_map)
3087         {
3088                 R_BuildWhiteCube();
3089                 R_BuildNormalizationCube();
3090         }
3091         r_texture_fogattenuation = NULL;
3092         r_texture_fogheighttexture = NULL;
3093         r_texture_gammaramps = NULL;
3094         //r_texture_fogintensity = NULL;
3095         memset(&r_fb, 0, sizeof(r_fb));
3096         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
3097         r_glsl_permutation = NULL;
3098         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3099         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3100         memset(&r_svbsp, 0, sizeof (r_svbsp));
3101
3102         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3103         r_texture_numcubemaps = 0;
3104
3105         r_refdef.fogmasktable_density = 0;
3106
3107 #ifdef __ANDROID__
3108         // For Steelstorm Android
3109         // FIXME CACHE the program and reload
3110         // FIXME see possible combinations for SS:BR android
3111         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
3112         R_SetupShader_SetPermutationGLSL(0, 12);
3113         R_SetupShader_SetPermutationGLSL(0, 13);
3114         R_SetupShader_SetPermutationGLSL(0, 8388621);
3115         R_SetupShader_SetPermutationGLSL(3, 0);
3116         R_SetupShader_SetPermutationGLSL(3, 2048);
3117         R_SetupShader_SetPermutationGLSL(5, 0);
3118         R_SetupShader_SetPermutationGLSL(5, 2);
3119         R_SetupShader_SetPermutationGLSL(5, 2048);
3120         R_SetupShader_SetPermutationGLSL(5, 8388608);
3121         R_SetupShader_SetPermutationGLSL(11, 1);
3122         R_SetupShader_SetPermutationGLSL(11, 2049);
3123         R_SetupShader_SetPermutationGLSL(11, 8193);
3124         R_SetupShader_SetPermutationGLSL(11, 10241);
3125         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
3126 #endif
3127 }
3128
3129 static void gl_main_shutdown(void)
3130 {
3131         R_RenderTarget_FreeUnused(true);
3132         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
3133         R_AnimCache_Free();
3134         R_FrameData_Reset();
3135         R_BufferData_Reset();
3136
3137         R_Main_FreeViewCache();
3138
3139         switch(vid.renderpath)
3140         {
3141         case RENDERPATH_GL20:
3142         case RENDERPATH_GLES2:
3143 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
3144                 if (r_maxqueries)
3145                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3146 #endif
3147                 break;
3148         }
3149
3150         r_numqueries = 0;
3151         r_maxqueries = 0;
3152         memset(r_queries, 0, sizeof(r_queries));
3153
3154         r_qwskincache = NULL;
3155         r_qwskincache_size = 0;
3156
3157         // clear out the r_skinframe state
3158         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3159         memset(&r_skinframe, 0, sizeof(r_skinframe));
3160
3161         if (r_svbsp.nodes)
3162                 Mem_Free(r_svbsp.nodes);
3163         memset(&r_svbsp, 0, sizeof (r_svbsp));
3164         R_FreeTexturePool(&r_main_texturepool);
3165         loadingscreentexture = NULL;
3166         r_texture_blanknormalmap = NULL;
3167         r_texture_white = NULL;
3168         r_texture_grey128 = NULL;
3169         r_texture_black = NULL;
3170         r_texture_whitecube = NULL;
3171         r_texture_normalizationcube = NULL;
3172         r_texture_fogattenuation = NULL;
3173         r_texture_fogheighttexture = NULL;
3174         r_texture_gammaramps = NULL;
3175         r_texture_numcubemaps = 0;
3176         //r_texture_fogintensity = NULL;
3177         memset(&r_fb, 0, sizeof(r_fb));
3178         R_GLSL_Restart_f();
3179
3180         r_glsl_permutation = NULL;
3181         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3182         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3183 }
3184
3185 static void gl_main_newmap(void)
3186 {
3187         // FIXME: move this code to client
3188         char *entities, entname[MAX_QPATH];
3189         if (r_qwskincache)
3190                 Mem_Free(r_qwskincache);
3191         r_qwskincache = NULL;
3192         r_qwskincache_size = 0;
3193         if (cl.worldmodel)
3194         {
3195                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3196                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3197                 {
3198                         CL_ParseEntityLump(entities);
3199                         Mem_Free(entities);
3200                         return;
3201                 }
3202                 if (cl.worldmodel->brush.entities)
3203                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3204         }
3205         R_Main_FreeViewCache();
3206
3207         R_FrameData_Reset();
3208         R_BufferData_Reset();
3209 }
3210
3211 void GL_Main_Init(void)
3212 {
3213         int i;
3214         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3215         R_InitShaderModeInfo();
3216
3217         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3218         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3219         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3220         if (gamemode == GAME_NEHAHRA)
3221         {
3222                 Cvar_RegisterVariable (&gl_fogenable);
3223                 Cvar_RegisterVariable (&gl_fogdensity);
3224                 Cvar_RegisterVariable (&gl_fogred);
3225                 Cvar_RegisterVariable (&gl_foggreen);
3226                 Cvar_RegisterVariable (&gl_fogblue);
3227                 Cvar_RegisterVariable (&gl_fogstart);
3228                 Cvar_RegisterVariable (&gl_fogend);
3229                 Cvar_RegisterVariable (&gl_skyclip);
3230         }
3231         Cvar_RegisterVariable(&r_motionblur);
3232         Cvar_RegisterVariable(&r_damageblur);
3233         Cvar_RegisterVariable(&r_motionblur_averaging);
3234         Cvar_RegisterVariable(&r_motionblur_randomize);
3235         Cvar_RegisterVariable(&r_motionblur_minblur);
3236         Cvar_RegisterVariable(&r_motionblur_maxblur);
3237         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
3238         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
3239         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
3240         Cvar_RegisterVariable(&r_motionblur_mousefactor);
3241         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
3242         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
3243         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3244         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3245         Cvar_RegisterVariable(&r_equalize_entities_by);
3246         Cvar_RegisterVariable(&r_equalize_entities_to);
3247         Cvar_RegisterVariable(&r_depthfirst);
3248         Cvar_RegisterVariable(&r_useinfinitefarclip);
3249         Cvar_RegisterVariable(&r_farclip_base);
3250         Cvar_RegisterVariable(&r_farclip_world);
3251         Cvar_RegisterVariable(&r_nearclip);
3252         Cvar_RegisterVariable(&r_deformvertexes);
3253         Cvar_RegisterVariable(&r_transparent);
3254         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
3255         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
3256         Cvar_RegisterVariable(&r_transparent_useplanardistance);
3257         Cvar_RegisterVariable(&r_showoverdraw);
3258         Cvar_RegisterVariable(&r_showbboxes);
3259         Cvar_RegisterVariable(&r_showbboxes_client);
3260         Cvar_RegisterVariable(&r_showsurfaces);
3261         Cvar_RegisterVariable(&r_showtris);
3262         Cvar_RegisterVariable(&r_shownormals);
3263         Cvar_RegisterVariable(&r_showlighting);
3264         Cvar_RegisterVariable(&r_showcollisionbrushes);
3265         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3266         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3267         Cvar_RegisterVariable(&r_showdisabledepthtest);
3268         Cvar_RegisterVariable(&r_showspriteedges);
3269         Cvar_RegisterVariable(&r_showparticleedges);
3270         Cvar_RegisterVariable(&r_drawportals);
3271         Cvar_RegisterVariable(&r_drawentities);
3272         Cvar_RegisterVariable(&r_draw2d);
3273         Cvar_RegisterVariable(&r_drawworld);
3274         Cvar_RegisterVariable(&r_cullentities_trace);
3275         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
3276         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3277         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3278         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3279         Cvar_RegisterVariable(&r_cullentities_trace_expand);
3280         Cvar_RegisterVariable(&r_cullentities_trace_pad);
3281         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3282         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
3283         Cvar_RegisterVariable(&r_sortentities);
3284         Cvar_RegisterVariable(&r_drawviewmodel);
3285         Cvar_RegisterVariable(&r_drawexteriormodel);
3286         Cvar_RegisterVariable(&r_speeds);
3287         Cvar_RegisterVariable(&r_fullbrights);
3288         Cvar_RegisterVariable(&r_wateralpha);
3289         Cvar_RegisterVariable(&r_dynamic);
3290         Cvar_RegisterVariable(&r_fakelight);
3291         Cvar_RegisterVariable(&r_fakelight_intensity);
3292         Cvar_RegisterVariable(&r_fullbright_directed);
3293         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
3294         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
3295         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
3296         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
3297         Cvar_RegisterVariable(&r_fullbright);
3298         Cvar_RegisterVariable(&r_shadows);
3299         Cvar_RegisterVariable(&r_shadows_darken);
3300         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3301         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3302         Cvar_RegisterVariable(&r_shadows_throwdistance);
3303         Cvar_RegisterVariable(&r_shadows_throwdirection);
3304         Cvar_RegisterVariable(&r_shadows_focus);
3305         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
3306         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
3307         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3308         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3309         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3310         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3311         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3312         Cvar_RegisterVariable(&r_fog_exp2);
3313         Cvar_RegisterVariable(&r_fog_clear);
3314         Cvar_RegisterVariable(&r_drawfog);
3315         Cvar_RegisterVariable(&r_transparentdepthmasking);
3316         Cvar_RegisterVariable(&r_transparent_sortmindist);
3317         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
3318         Cvar_RegisterVariable(&r_transparent_sortarraysize);
3319         Cvar_RegisterVariable(&r_texture_dds_load);
3320         Cvar_RegisterVariable(&r_texture_dds_save);
3321         Cvar_RegisterVariable(&r_textureunits);
3322         Cvar_RegisterVariable(&gl_combine);
3323         Cvar_RegisterVariable(&r_usedepthtextures);
3324         Cvar_RegisterVariable(&r_viewfbo);
3325         Cvar_RegisterVariable(&r_rendertarget_debug);
3326         Cvar_RegisterVariable(&r_viewscale);
3327         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
3328         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
3329         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
3330         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
3331         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
3332         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
3333         Cvar_RegisterVariable(&r_glsl);
3334         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3335         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3336         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
3337         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3338         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
3339         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
3340         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3341         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
3342         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
3343         Cvar_RegisterVariable(&r_glsl_postprocess);
3344         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3345         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3346         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3347         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3348         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
3349         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
3350         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
3351         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
3352         Cvar_RegisterVariable(&r_celshading);
3353         Cvar_RegisterVariable(&r_celoutlines);
3354
3355         Cvar_RegisterVariable(&r_water);
3356         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
3357         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3358         Cvar_RegisterVariable(&r_water_clippingplanebias);
3359         Cvar_RegisterVariable(&r_water_refractdistort);
3360         Cvar_RegisterVariable(&r_water_reflectdistort);
3361         Cvar_RegisterVariable(&r_water_scissormode);
3362         Cvar_RegisterVariable(&r_water_lowquality);
3363         Cvar_RegisterVariable(&r_water_hideplayer);
3364
3365         Cvar_RegisterVariable(&r_lerpsprites);
3366         Cvar_RegisterVariable(&r_lerpmodels);
3367         Cvar_RegisterVariable(&r_lerplightstyles);
3368         Cvar_RegisterVariable(&r_waterscroll);
3369         Cvar_RegisterVariable(&r_bloom);
3370         Cvar_RegisterVariable(&r_bloom_colorscale);
3371         Cvar_RegisterVariable(&r_bloom_brighten);
3372         Cvar_RegisterVariable(&r_bloom_blur);
3373         Cvar_RegisterVariable(&r_bloom_resolution);
3374         Cvar_RegisterVariable(&r_bloom_colorexponent);
3375         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3376         Cvar_RegisterVariable(&r_bloom_scenebrightness);
3377         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3378         Cvar_RegisterVariable(&r_hdr_glowintensity);
3379         Cvar_RegisterVariable(&r_hdr_irisadaptation);
3380         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
3381         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
3382         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
3383         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
3384         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
3385         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
3386         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
3387         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3388         Cvar_RegisterVariable(&developer_texturelogging);
3389         Cvar_RegisterVariable(&gl_lightmaps);
3390         Cvar_RegisterVariable(&r_test);
3391         Cvar_RegisterVariable(&r_batch_multidraw);
3392         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
3393         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
3394         Cvar_RegisterVariable(&r_glsl_skeletal);
3395         Cvar_RegisterVariable(&r_glsl_saturation);
3396         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
3397         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
3398         Cvar_RegisterVariable(&r_framedatasize);
3399         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
3400                 Cvar_RegisterVariable(&r_buffermegs[i]);
3401         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
3402         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3403                 Cvar_SetValue("r_fullbrights", 0);
3404 #ifdef DP_MOBILETOUCH
3405         // GLES devices have terrible depth precision in general, so...
3406         Cvar_SetValueQuick(&r_nearclip, 4);
3407         Cvar_SetValueQuick(&r_farclip_base, 4096);
3408         Cvar_SetValueQuick(&r_farclip_world, 0);
3409         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
3410 #endif
3411         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
3412 }
3413
3414 void Render_Init(void)
3415 {
3416         gl_backend_init();
3417         R_Textures_Init();
3418         GL_Main_Init();
3419         Font_Init();
3420         GL_Draw_Init();
3421         R_Shadow_Init();
3422         R_Sky_Init();
3423         GL_Surf_Init();
3424         Sbar_Init();
3425         R_Particles_Init();
3426         R_Explosion_Init();
3427         R_LightningBeams_Init();
3428         Mod_RenderInit();
3429 }
3430
3431 /*
3432 ===============
3433 GL_Init
3434 ===============
3435 */
3436 #ifndef USE_GLES2
3437 extern char *ENGINE_EXTENSIONS;
3438 void GL_Init (void)
3439 {
3440         gl_renderer = (const char *)qglGetString(GL_RENDERER);
3441         gl_vendor = (const char *)qglGetString(GL_VENDOR);
3442         gl_version = (const char *)qglGetString(GL_VERSION);
3443         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3444
3445         if (!gl_extensions)
3446                 gl_extensions = "";
3447         if (!gl_platformextensions)
3448                 gl_platformextensions = "";
3449
3450         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3451         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3452         Con_Printf("GL_VERSION: %s\n", gl_version);
3453         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3454         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3455
3456         VID_CheckExtensions();
3457
3458         // LordHavoc: report supported extensions
3459 #ifdef CONFIG_MENU
3460         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3461 #else
3462         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
3463 #endif
3464
3465         // clear to black (loading plaque will be seen over this)
3466         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
3467 }
3468 #endif
3469
3470 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3471 {
3472         int i;
3473         mplane_t *p;
3474         if (r_trippy.integer)
3475                 return false;
3476         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3477         {
3478                 p = r_refdef.view.frustum + i;
3479                 switch(p->signbits)
3480                 {
3481                 default:
3482                 case 0:
3483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3484                                 return true;
3485                         break;
3486                 case 1:
3487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3488                                 return true;
3489                         break;
3490                 case 2:
3491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3492                                 return true;
3493                         break;
3494                 case 3:
3495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3496                                 return true;
3497                         break;
3498                 case 4:
3499                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3500                                 return true;
3501                         break;
3502                 case 5:
3503                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3504                                 return true;
3505                         break;
3506                 case 6:
3507                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3508                                 return true;
3509                         break;
3510                 case 7:
3511                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3512                                 return true;
3513                         break;
3514                 }
3515         }
3516         return false;
3517 }
3518
3519 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3520 {
3521         int i;
3522         const mplane_t *p;
3523         if (r_trippy.integer)
3524                 return false;
3525         for (i = 0;i < numplanes;i++)
3526         {
3527                 p = planes + i;
3528                 switch(p->signbits)
3529                 {
3530                 default:
3531                 case 0:
3532                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3533                                 return true;
3534                         break;
3535                 case 1:
3536                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3537                                 return true;
3538                         break;
3539                 case 2:
3540                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3541                                 return true;
3542                         break;
3543                 case 3:
3544                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3545                                 return true;
3546                         break;
3547                 case 4:
3548                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3549                                 return true;
3550                         break;
3551                 case 5:
3552                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3553                                 return true;
3554                         break;
3555                 case 6:
3556                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3557                                 return true;
3558                         break;
3559                 case 7:
3560                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3561                                 return true;
3562                         break;
3563                 }
3564         }
3565         return false;
3566 }
3567
3568 //==================================================================================
3569
3570 // LordHavoc: this stores temporary data used within the same frame
3571
3572 typedef struct r_framedata_mem_s
3573 {
3574         struct r_framedata_mem_s *purge; // older mem block to free on next frame
3575         size_t size; // how much usable space
3576         size_t current; // how much space in use
3577         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
3578         size_t wantedsize; // how much space was allocated
3579         unsigned char *data; // start of real data (16byte aligned)
3580 }
3581 r_framedata_mem_t;
3582
3583 static r_framedata_mem_t *r_framedata_mem;
3584
3585 void R_FrameData_Reset(void)
3586 {
3587         while (r_framedata_mem)
3588         {
3589                 r_framedata_mem_t *next = r_framedata_mem->purge;
3590                 Mem_Free(r_framedata_mem);
3591                 r_framedata_mem = next;
3592         }
3593 }
3594
3595 static void R_FrameData_Resize(qboolean mustgrow)
3596 {
3597         size_t wantedsize;
3598         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3599         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
3600         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
3601         {
3602                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
3603                 newmem->wantedsize = wantedsize;
3604                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
3605                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
3606                 newmem->current = 0;
3607                 newmem->mark = 0;
3608                 newmem->purge = r_framedata_mem;
3609                 r_framedata_mem = newmem;
3610         }
3611 }
3612
3613 void R_FrameData_NewFrame(void)
3614 {
3615         R_FrameData_Resize(false);
3616         if (!r_framedata_mem)
3617                 return;
3618         // if we ran out of space on the last frame, free the old memory now
3619         while (r_framedata_mem->purge)
3620         {
3621                 // repeatedly remove the second item in the list, leaving only head
3622                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
3623                 Mem_Free(r_framedata_mem->purge);
3624                 r_framedata_mem->purge = next;
3625         }
3626         // reset the current mem pointer
3627         r_framedata_mem->current = 0;
3628         r_framedata_mem->mark = 0;
3629 }
3630
3631 void *R_FrameData_Alloc(size_t size)
3632 {
3633         void *data;
3634         float newvalue;
3635
3636         // align to 16 byte boundary - the data pointer is already aligned, so we
3637         // only need to ensure the size of every allocation is also aligned
3638         size = (size + 15) & ~15;
3639
3640         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
3641         {
3642                 // emergency - we ran out of space, allocate more memory
3643                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
3644                 newvalue = r_framedatasize.value * 2.0f;
3645                 // 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
3646                 if (sizeof(size_t) >= 8)
3647                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
3648                 else
3649                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
3650                 // this might not be a growing it, but we'll allocate another buffer every time
3651                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
3652                 R_FrameData_Resize(true);
3653         }
3654
3655         data = r_framedata_mem->data + r_framedata_mem->current;
3656         r_framedata_mem->current += size;
3657
3658         // count the usage for stats
3659         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
3660         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
3661
3662         return (void *)data;
3663 }
3664
3665 void *R_FrameData_Store(size_t size, void *data)
3666 {
3667         void *d = R_FrameData_Alloc(size);
3668         if (d && data)
3669                 memcpy(d, data, size);
3670         return d;
3671 }
3672
3673 void R_FrameData_SetMark(void)
3674 {
3675         if (!r_framedata_mem)
3676                 return;
3677         r_framedata_mem->mark = r_framedata_mem->current;
3678 }
3679
3680 void R_FrameData_ReturnToMark(void)
3681 {
3682         if (!r_framedata_mem)
3683                 return;
3684         r_framedata_mem->current = r_framedata_mem->mark;
3685 }
3686
3687 //==================================================================================
3688
3689 // avoid reusing the same buffer objects on consecutive frames
3690 #define R_BUFFERDATA_CYCLE 3
3691
3692 typedef struct r_bufferdata_buffer_s
3693 {
3694         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
3695         size_t size; // how much usable space
3696         size_t current; // how much space in use
3697         r_meshbuffer_t *buffer; // the buffer itself
3698 }
3699 r_bufferdata_buffer_t;
3700
3701 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
3702 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
3703
3704 /// frees all dynamic buffers
3705 void R_BufferData_Reset(void)
3706 {
3707         int cycle, type;
3708         r_bufferdata_buffer_t **p, *mem;
3709         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
3710         {
3711                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3712                 {
3713                         // free all buffers
3714                         p = &r_bufferdata_buffer[cycle][type];
3715                         while (*p)
3716                         {
3717                                 mem = *p;
3718                                 *p = (*p)->purge;
3719                                 if (mem->buffer)
3720                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3721                                 Mem_Free(mem);
3722                         }
3723                 }
3724         }
3725 }
3726
3727 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
3728 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
3729 {
3730         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3731         size_t size;
3732         float newvalue = r_buffermegs[type].value;
3733
3734         // increase the cvar if we have to (but only if we already have a mem)
3735         if (mustgrow && mem)
3736                 newvalue *= 2.0f;
3737         newvalue = bound(0.25f, newvalue, 256.0f);
3738         while (newvalue * 1024*1024 < minsize)
3739                 newvalue *= 2.0f;
3740
3741         // clamp the cvar to valid range
3742         newvalue = bound(0.25f, newvalue, 256.0f);
3743         if (r_buffermegs[type].value != newvalue)
3744                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
3745
3746         // calculate size in bytes
3747         size = (size_t)(newvalue * 1024*1024);
3748         size = bound(131072, size, 256*1024*1024);
3749
3750         // allocate a new buffer if the size is different (purge old one later)
3751         // or if we were told we must grow the buffer
3752         if (!mem || mem->size != size || mustgrow)
3753         {
3754                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
3755                 mem->size = size;
3756                 mem->current = 0;
3757                 if (type == R_BUFFERDATA_VERTEX)
3758                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
3759                 else if (type == R_BUFFERDATA_INDEX16)
3760                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
3761                 else if (type == R_BUFFERDATA_INDEX32)
3762                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
3763                 else if (type == R_BUFFERDATA_UNIFORM)
3764                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
3765                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
3766                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
3767         }
3768 }
3769
3770 void R_BufferData_NewFrame(void)
3771 {
3772         int type;
3773         r_bufferdata_buffer_t **p, *mem;
3774         // cycle to the next frame's buffers
3775         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
3776         // if we ran out of space on the last time we used these buffers, free the old memory now
3777         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3778         {
3779                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
3780                 {
3781                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
3782                         // free all but the head buffer, this is how we recycle obsolete
3783                         // buffers after they are no longer in use
3784                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
3785                         while (*p)
3786                         {
3787                                 mem = *p;
3788                                 *p = (*p)->purge;
3789                                 if (mem->buffer)
3790                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3791                                 Mem_Free(mem);
3792                         }
3793                         // reset the current offset
3794                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
3795                 }
3796         }
3797 }
3798
3799 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
3800 {
3801         r_bufferdata_buffer_t *mem;
3802         int offset = 0;
3803         int padsize;
3804
3805         *returnbufferoffset = 0;
3806
3807         // align size to a byte boundary appropriate for the buffer type, this
3808         // makes all allocations have aligned start offsets
3809         if (type == R_BUFFERDATA_UNIFORM)
3810                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
3811         else
3812                 padsize = (datasize + 15) & ~15;
3813
3814         // if we ran out of space in this buffer we must allocate a new one
3815         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)
3816                 R_BufferData_Resize(type, true, padsize);
3817
3818         // if the resize did not give us enough memory, fail
3819         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)
3820                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
3821
3822         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3823         offset = (int)mem->current;
3824         mem->current += padsize;
3825
3826         // upload the data to the buffer at the chosen offset
3827         if (offset == 0)
3828                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
3829         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
3830
3831         // count the usage for stats
3832         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
3833         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
3834
3835         // return the buffer offset
3836         *returnbufferoffset = offset;
3837
3838         return mem->buffer;
3839 }
3840
3841 //==================================================================================
3842
3843 // LordHavoc: animcache originally written by Echon, rewritten since then
3844
3845 /**
3846  * Animation cache prevents re-generating mesh data for an animated model
3847  * multiple times in one frame for lighting, shadowing, reflections, etc.
3848  */
3849
3850 void R_AnimCache_Free(void)
3851 {
3852 }
3853
3854 void R_AnimCache_ClearCache(void)
3855 {
3856         int i;
3857         entity_render_t *ent;
3858
3859         for (i = 0;i < r_refdef.scene.numentities;i++)
3860         {
3861                 ent = r_refdef.scene.entities[i];
3862                 ent->animcache_vertex3f = NULL;
3863                 ent->animcache_vertex3f_vertexbuffer = NULL;
3864                 ent->animcache_vertex3f_bufferoffset = 0;
3865                 ent->animcache_normal3f = NULL;
3866                 ent->animcache_normal3f_vertexbuffer = NULL;
3867                 ent->animcache_normal3f_bufferoffset = 0;
3868                 ent->animcache_svector3f = NULL;
3869                 ent->animcache_svector3f_vertexbuffer = NULL;
3870                 ent->animcache_svector3f_bufferoffset = 0;
3871                 ent->animcache_tvector3f = NULL;
3872                 ent->animcache_tvector3f_vertexbuffer = NULL;
3873                 ent->animcache_tvector3f_bufferoffset = 0;
3874                 ent->animcache_skeletaltransform3x4 = NULL;
3875                 ent->animcache_skeletaltransform3x4buffer = NULL;
3876                 ent->animcache_skeletaltransform3x4offset = 0;
3877                 ent->animcache_skeletaltransform3x4size = 0;
3878         }
3879 }
3880
3881 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3882 {
3883         dp_model_t *model = ent->model;
3884         int numvertices;
3885
3886         // see if this ent is worth caching
3887         if (!model || !model->Draw || !model->AnimateVertices)
3888                 return false;
3889         // nothing to cache if it contains no animations and has no skeleton
3890         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
3891                 return false;
3892         // see if it is already cached for gpuskeletal
3893         if (ent->animcache_skeletaltransform3x4)
3894                 return false;
3895         // see if it is already cached as a mesh
3896         if (ent->animcache_vertex3f)
3897         {
3898                 // check if we need to add normals or tangents
3899                 if (ent->animcache_normal3f)
3900                         wantnormals = false;
3901                 if (ent->animcache_svector3f)
3902                         wanttangents = false;
3903                 if (!wantnormals && !wanttangents)
3904                         return false;
3905         }
3906
3907         // check which kind of cache we need to generate
3908         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
3909         {
3910                 // cache the skeleton so the vertex shader can use it
3911                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
3912                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
3913                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
3914                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
3915                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
3916                 // note: this can fail if the buffer is at the grow limit
3917                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
3918                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
3919         }
3920         else if (ent->animcache_vertex3f)
3921         {
3922                 // mesh was already cached but we may need to add normals/tangents
3923                 // (this only happens with multiple views, reflections, cameras, etc)
3924                 if (wantnormals || wanttangents)
3925                 {
3926                         numvertices = model->surfmesh.num_vertices;
3927                         if (wantnormals)
3928                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3929                         if (wanttangents)
3930                         {
3931                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3932                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3933                         }
3934                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3935                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3936                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3937                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3938                 }
3939         }
3940         else
3941         {
3942                 // generate mesh cache
3943                 numvertices = model->surfmesh.num_vertices;
3944                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3945                 if (wantnormals)
3946                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3947                 if (wanttangents)
3948                 {
3949                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3950                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3951                 }
3952                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3953                 if (wantnormals || wanttangents)
3954                 {
3955                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3956                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3957                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3958                 }
3959                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
3960                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
3961                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
3962         }
3963         return true;
3964 }
3965
3966 void R_AnimCache_CacheVisibleEntities(void)
3967 {
3968         int i;
3969
3970         // TODO: thread this
3971         // NOTE: R_PrepareRTLights() also caches entities
3972
3973         for (i = 0;i < r_refdef.scene.numentities;i++)
3974                 if (r_refdef.viewcache.entityvisible[i])
3975                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], true, true);
3976 }
3977
3978 //==================================================================================
3979
3980 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3981 {
3982         int i;
3983         vec3_t eyemins, eyemaxs;
3984         vec3_t boxmins, boxmaxs;
3985         vec3_t padmins, padmaxs;
3986         vec3_t start;
3987         vec3_t end;
3988         dp_model_t *model = r_refdef.scene.worldmodel;
3989         static vec3_t positions[] = {
3990                 { 0.5f, 0.5f, 0.5f },
3991                 { 0.0f, 0.0f, 0.0f },
3992                 { 0.0f, 0.0f, 1.0f },
3993                 { 0.0f, 1.0f, 0.0f },
3994                 { 0.0f, 1.0f, 1.0f },
3995                 { 1.0f, 0.0f, 0.0f },
3996                 { 1.0f, 0.0f, 1.0f },
3997                 { 1.0f, 1.0f, 0.0f },
3998                 { 1.0f, 1.0f, 1.0f },
3999         };
4000
4001         // sample count can be set to -1 to skip this logic, for flicker-prone objects
4002         if (numsamples < 0)
4003                 return true;
4004
4005         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
4006         if (!r_refdef.view.usevieworiginculling)
4007                 return true;
4008
4009         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
4010                 return true;
4011
4012         // expand the eye box a little
4013         eyemins[0] = eye[0] - eyejitter;
4014         eyemaxs[0] = eye[0] + eyejitter;
4015         eyemins[1] = eye[1] - eyejitter;
4016         eyemaxs[1] = eye[1] + eyejitter;
4017         eyemins[2] = eye[2] - eyejitter;
4018         eyemaxs[2] = eye[2] + eyejitter;
4019         // expand the box a little
4020         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
4021         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
4022         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
4023         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
4024         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
4025         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
4026         // make an even larger box for the acceptable area
4027         padmins[0] = boxmins[0] - pad;
4028         padmaxs[0] = boxmaxs[0] + pad;
4029         padmins[1] = boxmins[1] - pad;
4030         padmaxs[1] = boxmaxs[1] + pad;
4031         padmins[2] = boxmins[2] - pad;
4032         padmaxs[2] = boxmaxs[2] + pad;
4033
4034         // return true if eye overlaps enlarged box
4035         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
4036                 return true;
4037
4038         // try specific positions in the box first - note that these can be cached
4039         if (r_cullentities_trace_entityocclusion.integer)
4040         {
4041                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
4042                 {
4043                         VectorCopy(eye, start);
4044                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
4045                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
4046                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
4047                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
4048                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
4049                         // not picky - if the trace ended anywhere in the box we're good
4050                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
4051                                 return true;
4052                 }
4053         }
4054         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
4055                 return true;
4056
4057         // try various random positions
4058         for (i = 0; i < numsamples; i++)
4059         {
4060                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
4061                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4062                 if (r_cullentities_trace_entityocclusion.integer)
4063                 {
4064                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
4065                         // not picky - if the trace ended anywhere in the box we're good
4066                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
4067                                 return true;
4068                 }
4069                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
4070                         return true;
4071         }
4072
4073         return false;
4074 }
4075
4076
4077 static void R_View_UpdateEntityVisible (void)
4078 {
4079         int i;
4080         int renderimask;
4081         int samples;
4082         entity_render_t *ent;
4083
4084         if (r_refdef.envmap || r_fb.water.hideplayer)
4085                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
4086         else if (chase_active.integer || r_fb.water.renderingscene)
4087                 renderimask = RENDER_VIEWMODEL;
4088         else
4089                 renderimask = RENDER_EXTERIORMODEL;
4090         if (!r_drawviewmodel.integer)
4091                 renderimask |= RENDER_VIEWMODEL;
4092         if (!r_drawexteriormodel.integer)
4093                 renderimask |= RENDER_EXTERIORMODEL;
4094         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4095         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4096         {
4097                 // worldmodel can check visibility
4098                 for (i = 0;i < r_refdef.scene.numentities;i++)
4099                 {
4100                         ent = r_refdef.scene.entities[i];
4101                         if (!(ent->flags & renderimask))
4102                         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)))
4103                         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))
4104                                 r_refdef.viewcache.entityvisible[i] = true;
4105                 }
4106         }
4107         else
4108         {
4109                 // no worldmodel or it can't check visibility
4110                 for (i = 0;i < r_refdef.scene.numentities;i++)
4111                 {
4112                         ent = r_refdef.scene.entities[i];
4113                         if (!(ent->flags & renderimask))
4114                         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)))
4115                                 r_refdef.viewcache.entityvisible[i] = true;
4116                 }
4117         }
4118         if (r_cullentities_trace.integer)
4119         {
4120                 for (i = 0;i < r_refdef.scene.numentities;i++)
4121                 {
4122                         if (!r_refdef.viewcache.entityvisible[i])
4123                                 continue;
4124                         ent = r_refdef.scene.entities[i];
4125                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4126                         {
4127                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
4128                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_cullentities_trace_expand.value, r_cullentities_trace_pad.value, r_refdef.view.origin, ent->mins, ent->maxs))
4129                                         ent->last_trace_visibility = realtime;
4130                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4131                                         r_refdef.viewcache.entityvisible[i] = 0;
4132                         }
4133                 }
4134         }
4135 }
4136
4137 /// only used if skyrendermasked, and normally returns false
4138 static int R_DrawBrushModelsSky (void)
4139 {
4140         int i, sky;
4141         entity_render_t *ent;
4142
4143         sky = false;
4144         for (i = 0;i < r_refdef.scene.numentities;i++)
4145         {
4146                 if (!r_refdef.viewcache.entityvisible[i])
4147                         continue;
4148                 ent = r_refdef.scene.entities[i];
4149                 if (!ent->model || !ent->model->DrawSky)
4150                         continue;
4151                 ent->model->DrawSky(ent);
4152                 sky = true;
4153         }
4154         return sky;
4155 }
4156
4157 static void R_DrawNoModel(entity_render_t *ent);
4158 static void R_DrawModels(void)
4159 {
4160         int i;
4161         entity_render_t *ent;
4162
4163         for (i = 0;i < r_refdef.scene.numentities;i++)
4164         {
4165                 if (!r_refdef.viewcache.entityvisible[i])
4166                         continue;
4167                 ent = r_refdef.scene.entities[i];
4168                 r_refdef.stats[r_stat_entities]++;
4169                 /*
4170                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4171                 {
4172                         vec3_t f, l, u, o;
4173                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4174                         Con_Printf("R_DrawModels\n");
4175                         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]);
4176                         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);
4177                         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);
4178                 }
4179                 */
4180                 if (ent->model && ent->model->Draw != NULL)
4181                         ent->model->Draw(ent);
4182                 else
4183                         R_DrawNoModel(ent);
4184         }
4185 }
4186
4187 static void R_DrawModelsDepth(void)
4188 {
4189         int i;
4190         entity_render_t *ent;
4191
4192         for (i = 0;i < r_refdef.scene.numentities;i++)
4193         {
4194                 if (!r_refdef.viewcache.entityvisible[i])
4195                         continue;
4196                 ent = r_refdef.scene.entities[i];
4197                 if (ent->model && ent->model->DrawDepth != NULL)
4198                         ent->model->DrawDepth(ent);
4199         }
4200 }
4201
4202 static void R_DrawModelsDebug(void)
4203 {
4204         int i;
4205         entity_render_t *ent;
4206
4207         for (i = 0;i < r_refdef.scene.numentities;i++)
4208         {
4209                 if (!r_refdef.viewcache.entityvisible[i])
4210                         continue;
4211                 ent = r_refdef.scene.entities[i];
4212                 if (ent->model && ent->model->DrawDebug != NULL)
4213                         ent->model->DrawDebug(ent);
4214         }
4215 }
4216
4217 static void R_DrawModelsAddWaterPlanes(void)
4218 {
4219         int i;
4220         entity_render_t *ent;
4221
4222         for (i = 0;i < r_refdef.scene.numentities;i++)
4223         {
4224                 if (!r_refdef.viewcache.entityvisible[i])
4225                         continue;
4226                 ent = r_refdef.scene.entities[i];
4227                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4228                         ent->model->DrawAddWaterPlanes(ent);
4229         }
4230 }
4231
4232 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}};
4233
4234 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4235 {
4236         if (r_hdr_irisadaptation.integer)
4237         {
4238                 vec3_t p;
4239                 vec3_t ambient;
4240                 vec3_t diffuse;
4241                 vec3_t diffusenormal;
4242                 vec3_t forward;
4243                 vec_t brightness = 0.0f;
4244                 vec_t goal;
4245                 vec_t current;
4246                 vec_t d;
4247                 int c;
4248                 VectorCopy(r_refdef.view.forward, forward);
4249                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
4250                 {
4251                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
4252                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
4253                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
4254                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
4255                         d = DotProduct(forward, diffusenormal);
4256                         brightness += VectorLength(ambient);
4257                         if (d > 0)
4258                                 brightness += d * VectorLength(diffuse);
4259                 }
4260                 brightness *= 1.0f / c;
4261                 brightness += 0.00001f; // make sure it's never zero
4262                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4263                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4264                 current = r_hdr_irisadaptation_value.value;
4265                 if (current < goal)
4266                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
4267                 else if (current > goal)
4268                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
4269                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4270                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4271         }
4272         else if (r_hdr_irisadaptation_value.value != 1.0f)
4273                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4274 }
4275
4276 static void R_View_SetFrustum(const int *scissor)
4277 {
4278         int i;
4279         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4280         vec3_t forward, left, up, origin, v;
4281
4282         if(scissor)
4283         {
4284                 // flipped x coordinates (because x points left here)
4285                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4286                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4287                 // non-flipped y coordinates
4288                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4289                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4290         }
4291
4292         // we can't trust r_refdef.view.forward and friends in reflected scenes
4293         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4294
4295 #if 0
4296         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4297         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4298         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4299         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4300         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4301         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4302         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4303         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4304         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4305         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4306         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4307         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4308 #endif
4309
4310 #if 0
4311         zNear = r_refdef.nearclip;
4312         nudge = 1.0 - 1.0 / (1<<23);
4313         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4314         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4315         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4316         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4317         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4318         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4319         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4320         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4321 #endif
4322
4323
4324
4325 #if 0
4326         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4327         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4328         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4329         r_refdef.view.frustum[0].dist = m[15] - m[12];
4330
4331         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4332         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4333         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4334         r_refdef.view.frustum[1].dist = m[15] + m[12];
4335
4336         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4337         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4338         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4339         r_refdef.view.frustum[2].dist = m[15] - m[13];
4340
4341         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4342         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4343         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4344         r_refdef.view.frustum[3].dist = m[15] + m[13];
4345
4346         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4347         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4348         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4349         r_refdef.view.frustum[4].dist = m[15] - m[14];
4350
4351         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4352         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4353         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4354         r_refdef.view.frustum[5].dist = m[15] + m[14];
4355 #endif
4356
4357         if (r_refdef.view.useperspective)
4358         {
4359                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4360                 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]);
4361                 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]);
4362                 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]);
4363                 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]);
4364
4365                 // then the normals from the corners relative to origin
4366                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4367                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4368                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4369                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4370
4371                 // in a NORMAL view, forward cross left == up
4372                 // in a REFLECTED view, forward cross left == down
4373                 // so our cross products above need to be adjusted for a left handed coordinate system
4374                 CrossProduct(forward, left, v);
4375                 if(DotProduct(v, up) < 0)
4376                 {
4377                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4378                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4379                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4380                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4381                 }
4382
4383                 // Leaving those out was a mistake, those were in the old code, and they
4384                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4385                 // I couldn't reproduce it after adding those normalizations. --blub
4386                 VectorNormalize(r_refdef.view.frustum[0].normal);
4387                 VectorNormalize(r_refdef.view.frustum[1].normal);
4388                 VectorNormalize(r_refdef.view.frustum[2].normal);
4389                 VectorNormalize(r_refdef.view.frustum[3].normal);
4390
4391                 // make the corners absolute
4392                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4393                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4394                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4395                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4396
4397                 // one more normal
4398                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4399
4400                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4401                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4402                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4403                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4404                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4405         }
4406         else
4407         {
4408                 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
4409                 VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
4410                 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
4411                 VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
4412                 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
4413                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
4414                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
4415                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
4416                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
4417                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
4418         }
4419         r_refdef.view.numfrustumplanes = 5;
4420
4421         if (r_refdef.view.useclipplane)
4422         {
4423                 r_refdef.view.numfrustumplanes = 6;
4424                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4425         }
4426
4427         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4428                 PlaneClassify(r_refdef.view.frustum + i);
4429
4430         // LordHavoc: note to all quake engine coders, Quake had a special case
4431         // for 90 degrees which assumed a square view (wrong), so I removed it,
4432         // Quake2 has it disabled as well.
4433
4434         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4435         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4436         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4437         //PlaneClassify(&frustum[0]);
4438
4439         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4440         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4441         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4442         //PlaneClassify(&frustum[1]);
4443
4444         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4445         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4446         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4447         //PlaneClassify(&frustum[2]);
4448
4449         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4450         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4451         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4452         //PlaneClassify(&frustum[3]);
4453
4454         // nearclip plane
4455         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4456         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4457         //PlaneClassify(&frustum[4]);
4458 }
4459
4460 static void R_View_UpdateWithScissor(const int *myscissor)
4461 {
4462         R_Main_ResizeViewCache();
4463         R_View_SetFrustum(myscissor);
4464         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4465         R_View_UpdateEntityVisible();
4466 }
4467
4468 static void R_View_Update(void)
4469 {
4470         R_Main_ResizeViewCache();
4471         R_View_SetFrustum(NULL);
4472         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4473         R_View_UpdateEntityVisible();
4474 }
4475
4476 float viewscalefpsadjusted = 1.0f;
4477
4478 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
4479 {
4480         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
4481         scale = bound(0.03125f, scale, 1.0f);
4482         *outwidth = (int)ceil(width * scale);
4483         *outheight = (int)ceil(height * scale);
4484 }
4485
4486 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4487 {
4488         const float *customclipplane = NULL;
4489         float plane[4];
4490         int /*rtwidth,*/ rtheight;
4491         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4492         {
4493                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
4494                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4495                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4496                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4497                         dist = r_refdef.view.clipplane.dist;
4498                 plane[0] = r_refdef.view.clipplane.normal[0];
4499                 plane[1] = r_refdef.view.clipplane.normal[1];
4500                 plane[2] = r_refdef.view.clipplane.normal[2];
4501                 plane[3] = -dist;
4502                 customclipplane = plane;
4503         }
4504
4505         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
4506         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
4507
4508         if (!r_refdef.view.useperspective)
4509                 R_Viewport_InitOrtho3D(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
4510         else if (vid.stencil && r_useinfinitefarclip.integer)
4511                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
4512         else
4513                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
4514         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4515         R_SetViewport(&r_refdef.view.viewport);
4516 }
4517
4518 void R_EntityMatrix(const matrix4x4_t *matrix)
4519 {
4520         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4521         {
4522                 gl_modelmatrixchanged = false;
4523                 gl_modelmatrix = *matrix;
4524                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4525                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4526                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4527                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4528                 CHECKGLERROR
4529                 switch(vid.renderpath)
4530                 {
4531                 case RENDERPATH_GL20:
4532                 case RENDERPATH_GLES2:
4533                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4534                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4535                         break;
4536                 }
4537         }
4538 }
4539
4540 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
4541 {
4542         r_viewport_t viewport;
4543
4544         CHECKGLERROR
4545
4546         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4547         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
4548         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4549         R_SetViewport(&viewport);
4550         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4551         GL_Color(1, 1, 1, 1);
4552         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4553         GL_BlendFunc(GL_ONE, GL_ZERO);
4554         GL_ScissorTest(false);
4555         GL_DepthMask(false);
4556         GL_DepthRange(0, 1);
4557         GL_DepthTest(false);
4558         GL_DepthFunc(GL_LEQUAL);
4559         R_EntityMatrix(&identitymatrix);
4560         R_Mesh_ResetTextureState();
4561         GL_PolygonOffset(0, 0);
4562         switch(vid.renderpath)
4563         {
4564         case RENDERPATH_GL20:
4565         case RENDERPATH_GLES2:
4566                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4567                 break;
4568         }
4569         GL_CullFace(GL_NONE);
4570
4571         CHECKGLERROR
4572 }
4573
4574 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4575 {
4576         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
4577 }
4578
4579 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4580 {
4581         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
4582         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4583         GL_Color(1, 1, 1, 1);
4584         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4585         GL_BlendFunc(GL_ONE, GL_ZERO);
4586         GL_ScissorTest(true);
4587         GL_DepthMask(true);
4588         GL_DepthRange(0, 1);
4589         GL_DepthTest(true);
4590         GL_DepthFunc(GL_LEQUAL);
4591         R_EntityMatrix(&identitymatrix);
4592         R_Mesh_ResetTextureState();
4593         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4594         switch(vid.renderpath)
4595         {
4596         case RENDERPATH_GL20:
4597         case RENDERPATH_GLES2:
4598                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4599                 break;
4600         }
4601         GL_CullFace(r_refdef.view.cullface_back);
4602 }
4603
4604 /*
4605 ================
4606 R_RenderView_UpdateViewVectors
4607 ================
4608 */
4609 void R_RenderView_UpdateViewVectors(void)
4610 {
4611         // break apart the view matrix into vectors for various purposes
4612         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4613         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4614         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4615         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4616         // make an inverted copy of the view matrix for tracking sprites
4617         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4618 }
4619
4620 void R_RenderTarget_FreeUnused(qboolean force)
4621 {
4622         int i, j, end;
4623         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4624         for (i = 0; i < end; i++)
4625         {
4626                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4627                 // free resources for rendertargets that have not been used for a while
4628                 // (note: this check is run after the frame render, so any targets used
4629                 // this frame will not be affected even at low framerates)
4630                 if (r && (realtime - r->lastusetime > 0.2 || force))
4631                 {
4632                         if (r->fbo)
4633                                 R_Mesh_DestroyFramebufferObject(r->fbo);
4634                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
4635                                 if (r->colortexture[j])
4636                                         R_FreeTexture(r->colortexture[j]);
4637                         if (r->depthtexture)
4638                                 R_FreeTexture(r->depthtexture);
4639                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
4640                 }
4641         }
4642 }
4643
4644 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
4645 {
4646         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
4647         x1 = x * iw;
4648         x2 = (x + w) * iw;
4649         y1 = (th - y) * ih;
4650         y2 = (th - y - h) * ih;
4651         texcoord2f[0] = x1;
4652         texcoord2f[2] = x2;
4653         texcoord2f[4] = x2;
4654         texcoord2f[6] = x1;
4655         texcoord2f[1] = y1;
4656         texcoord2f[3] = y1;
4657         texcoord2f[5] = y2;
4658         texcoord2f[7] = y2;
4659 }
4660
4661 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
4662 {
4663         int i, j, end;
4664         r_rendertarget_t *r = NULL;
4665         char vabuf[256];
4666         // first try to reuse an existing slot if possible
4667         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4668         for (i = 0; i < end; i++)
4669         {
4670                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4671                 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
4672                         break;
4673         }
4674         if (i == end)
4675         {
4676                 // no unused exact match found, so we have to make one in the first unused slot
4677                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
4678                 r->texturewidth = texturewidth;
4679                 r->textureheight = textureheight;
4680                 r->colortextype[0] = colortextype0;
4681                 r->colortextype[1] = colortextype1;
4682                 r->colortextype[2] = colortextype2;
4683                 r->colortextype[3] = colortextype3;
4684                 r->depthtextype = depthtextype;
4685                 r->depthisrenderbuffer = depthisrenderbuffer;
4686                 for (j = 0; j < 4; j++)
4687                         if (r->colortextype[j])
4688                                 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
4689                 if (r->depthtextype)
4690                 {
4691                         if (r->depthisrenderbuffer)
4692                                 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
4693                         else
4694                                 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
4695                 }
4696                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
4697         }
4698         r_refdef.stats[r_stat_rendertargets_used]++;
4699         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
4700         r->lastusetime = realtime;
4701         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
4702         return r;
4703 }
4704
4705 static void R_Water_StartFrame(void)
4706 {
4707         int waterwidth, waterheight;
4708
4709         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4710                 return;
4711
4712         // set waterwidth and waterheight to the water resolution that will be
4713         // used (often less than the screen resolution for faster rendering)
4714         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4715         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4716         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
4717
4718         if (!r_water.integer || r_showsurfaces.integer)
4719                 waterwidth = waterheight = 0;
4720
4721         // set up variables that will be used in shader setup
4722         r_fb.water.waterwidth = waterwidth;
4723         r_fb.water.waterheight = waterheight;
4724         r_fb.water.texturewidth = waterwidth;
4725         r_fb.water.textureheight = waterheight;
4726         r_fb.water.camerawidth = waterwidth;
4727         r_fb.water.cameraheight = waterheight;
4728         r_fb.water.screenscale[0] = 0.5f;
4729         r_fb.water.screenscale[1] = 0.5f;
4730         r_fb.water.screencenter[0] = 0.5f;
4731         r_fb.water.screencenter[1] = 0.5f;
4732         r_fb.water.enabled = waterwidth != 0;
4733
4734         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
4735         r_fb.water.numwaterplanes = 0;
4736 }
4737
4738 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
4739 {
4740         int planeindex, bestplaneindex, vertexindex;
4741         vec3_t mins, maxs, normal, center, v, n;
4742         vec_t planescore, bestplanescore;
4743         mplane_t plane;
4744         r_waterstate_waterplane_t *p;
4745         texture_t *t = R_GetCurrentTexture(surface->texture);
4746
4747         rsurface.texture = t;
4748         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
4749         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
4750         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
4751                 return;
4752         // average the vertex normals, find the surface bounds (after deformvertexes)
4753         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
4754         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
4755         VectorCopy(n, normal);
4756         VectorCopy(v, mins);
4757         VectorCopy(v, maxs);
4758         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
4759         {
4760                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
4761                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
4762                 VectorAdd(normal, n, normal);
4763                 mins[0] = min(mins[0], v[0]);
4764                 mins[1] = min(mins[1], v[1]);
4765                 mins[2] = min(mins[2], v[2]);
4766                 maxs[0] = max(maxs[0], v[0]);
4767                 maxs[1] = max(maxs[1], v[1]);
4768                 maxs[2] = max(maxs[2], v[2]);
4769         }
4770         VectorNormalize(normal);
4771         VectorMAM(0.5f, mins, 0.5f, maxs, center);
4772
4773         VectorCopy(normal, plane.normal);
4774         VectorNormalize(plane.normal);
4775         plane.dist = DotProduct(center, plane.normal);
4776         PlaneClassify(&plane);
4777         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4778         {
4779                 // skip backfaces (except if nocullface is set)
4780 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4781 //                      return;
4782                 VectorNegate(plane.normal, plane.normal);
4783                 plane.dist *= -1;
4784                 PlaneClassify(&plane);
4785         }
4786
4787
4788         // find a matching plane if there is one
4789         bestplaneindex = -1;
4790         bestplanescore = 1048576.0f;
4791         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4792         {
4793                 if(p->camera_entity == t->camera_entity)
4794                 {
4795                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
4796                         if (bestplaneindex < 0 || bestplanescore > planescore)
4797                         {
4798                                 bestplaneindex = planeindex;
4799                                 bestplanescore = planescore;
4800                         }
4801                 }
4802         }
4803         planeindex = bestplaneindex;
4804
4805         // if this surface does not fit any known plane rendered this frame, add one
4806         if (planeindex < 0 || bestplanescore > 0.001f)
4807         {
4808                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
4809                 {
4810                         // store the new plane
4811                         planeindex = r_fb.water.numwaterplanes++;
4812                         p = r_fb.water.waterplanes + planeindex;
4813                         p->plane = plane;
4814                         // clear materialflags and pvs
4815                         p->materialflags = 0;
4816                         p->pvsvalid = false;
4817                         p->camera_entity = t->camera_entity;
4818                         VectorCopy(mins, p->mins);
4819                         VectorCopy(maxs, p->maxs);
4820                 }
4821                 else
4822                 {
4823                         // We're totally screwed.
4824                         return;
4825                 }
4826         }
4827         else
4828         {
4829                 // merge mins/maxs when we're adding this surface to the plane
4830                 p = r_fb.water.waterplanes + planeindex;
4831                 p->mins[0] = min(p->mins[0], mins[0]);
4832                 p->mins[1] = min(p->mins[1], mins[1]);
4833                 p->mins[2] = min(p->mins[2], mins[2]);
4834                 p->maxs[0] = max(p->maxs[0], maxs[0]);
4835                 p->maxs[1] = max(p->maxs[1], maxs[1]);
4836                 p->maxs[2] = max(p->maxs[2], maxs[2]);
4837         }
4838         // merge this surface's materialflags into the waterplane
4839         p->materialflags |= t->currentmaterialflags;
4840         if(!(p->materialflags & MATERIALFLAG_CAMERA))
4841         {
4842                 // merge this surface's PVS into the waterplane
4843                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4844                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4845                 {
4846                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4847                         p->pvsvalid = true;
4848                 }
4849         }
4850 }
4851
4852 extern cvar_t r_drawparticles;
4853 extern cvar_t r_drawdecals;
4854
4855 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
4856 {
4857         int myscissor[4];
4858         r_refdef_view_t originalview;
4859         r_refdef_view_t myview;
4860         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;
4861         r_waterstate_waterplane_t *p;
4862         vec3_t visorigin;
4863         r_rendertarget_t *rt;
4864
4865         originalview = r_refdef.view;
4866
4867         // lowquality hack, temporarily shut down some cvars and restore afterwards
4868         qualityreduction = r_water_lowquality.integer;
4869         if (qualityreduction > 0)
4870         {
4871                 if (qualityreduction >= 1)
4872                 {
4873                         old_r_shadows = r_shadows.integer;
4874                         old_r_worldrtlight = r_shadow_realtime_world.integer;
4875                         old_r_dlight = r_shadow_realtime_dlight.integer;
4876                         Cvar_SetValueQuick(&r_shadows, 0);
4877                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
4878                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
4879                 }
4880                 if (qualityreduction >= 2)
4881                 {
4882                         old_r_dynamic = r_dynamic.integer;
4883                         old_r_particles = r_drawparticles.integer;
4884                         old_r_decals = r_drawdecals.integer;
4885                         Cvar_SetValueQuick(&r_dynamic, 0);
4886                         Cvar_SetValueQuick(&r_drawparticles, 0);
4887                         Cvar_SetValueQuick(&r_drawdecals, 0);
4888                 }
4889         }
4890
4891         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
4892         {
4893                 p->rt_reflection = NULL;
4894                 p->rt_refraction = NULL;
4895                 p->rt_camera = NULL;
4896         }
4897
4898         // render views
4899         r_refdef.view = originalview;
4900         r_refdef.view.showdebug = false;
4901         r_refdef.view.width = r_fb.water.waterwidth;
4902         r_refdef.view.height = r_fb.water.waterheight;
4903         r_refdef.view.useclipplane = true;
4904         myview = r_refdef.view;
4905         r_fb.water.renderingscene = true;
4906         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4907         {
4908                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
4909                         continue;
4910
4911                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4912                 {
4913                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
4914                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4915                                 goto error;
4916                         r_refdef.view = myview;
4917                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4918                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4919                         if(r_water_scissormode.integer)
4920                         {
4921                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4922                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4923                                 {
4924                                         p->rt_reflection = NULL;
4925                                         p->rt_refraction = NULL;
4926                                         p->rt_camera = NULL;
4927                                         continue;
4928                                 }
4929                         }
4930
4931                         r_refdef.view.clipplane = p->plane;
4932                         // reflected view origin may be in solid, so don't cull with it
4933                         r_refdef.view.usevieworiginculling = false;
4934                         // reverse the cullface settings for this render
4935                         r_refdef.view.cullface_front = GL_FRONT;
4936                         r_refdef.view.cullface_back = GL_BACK;
4937                         // combined pvs (based on what can be seen from each surface center)
4938                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4939                         {
4940                                 r_refdef.view.usecustompvs = true;
4941                                 if (p->pvsvalid)
4942                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4943                                 else
4944                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4945                         }
4946
4947                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
4948                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4949                         GL_ScissorTest(false);
4950                         R_ClearScreen(r_refdef.fogenabled);
4951                         GL_ScissorTest(true);
4952                         if(r_water_scissormode.integer & 2)
4953                                 R_View_UpdateWithScissor(myscissor);
4954                         else
4955                                 R_View_Update();
4956                         R_AnimCache_CacheVisibleEntities();
4957                         if(r_water_scissormode.integer & 1)
4958                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4959                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4960
4961                         r_fb.water.hideplayer = false;
4962                         p->rt_reflection = rt;
4963                 }
4964
4965                 // render the normal view scene and copy into texture
4966                 // (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)
4967                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4968                 {
4969                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
4970                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4971                                 goto error;
4972                         r_refdef.view = myview;
4973                         if(r_water_scissormode.integer)
4974                         {
4975                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4976                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4977                                 {
4978                                         p->rt_reflection = NULL;
4979                                         p->rt_refraction = NULL;
4980                                         p->rt_camera = NULL;
4981                                         continue;
4982                                 }
4983                         }
4984
4985                         // combined pvs (based on what can be seen from each surface center)
4986                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4987                         {
4988                                 r_refdef.view.usecustompvs = true;
4989                                 if (p->pvsvalid)
4990                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4991                                 else
4992                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4993                         }
4994
4995                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
4996
4997                         r_refdef.view.clipplane = p->plane;
4998                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4999                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5000
5001                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5002                         {
5003                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5004                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5005                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5006                                 R_RenderView_UpdateViewVectors();
5007                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5008                                 {
5009                                         r_refdef.view.usecustompvs = true;
5010                                         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);
5011                                 }
5012                         }
5013
5014                         PlaneClassify(&r_refdef.view.clipplane);
5015
5016                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5017                         GL_ScissorTest(false);
5018                         R_ClearScreen(r_refdef.fogenabled);
5019                         GL_ScissorTest(true);
5020                         if(r_water_scissormode.integer & 2)
5021                                 R_View_UpdateWithScissor(myscissor);
5022                         else
5023                                 R_View_Update();
5024                         R_AnimCache_CacheVisibleEntities();
5025                         if(r_water_scissormode.integer & 1)
5026                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5027                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5028
5029                         r_fb.water.hideplayer = false;
5030                         p->rt_refraction = rt;
5031                 }
5032                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5033                 {
5034                         rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5035                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
5036                                 goto error;
5037                         r_refdef.view = myview;
5038
5039                         r_refdef.view.clipplane = p->plane;
5040                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5041                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5042
5043                         r_refdef.view.width = r_fb.water.camerawidth;
5044                         r_refdef.view.height = r_fb.water.cameraheight;
5045                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5046                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5047                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5048                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5049
5050                         if(p->camera_entity)
5051                         {
5052                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5053                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5054                         }
5055
5056                         // note: all of the view is used for displaying... so
5057                         // there is no use in scissoring
5058
5059                         // reverse the cullface settings for this render
5060                         r_refdef.view.cullface_front = GL_FRONT;
5061                         r_refdef.view.cullface_back = GL_BACK;
5062                         // also reverse the view matrix
5063                         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
5064                         R_RenderView_UpdateViewVectors();
5065                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5066                         {
5067                                 r_refdef.view.usecustompvs = true;
5068                                 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);
5069                         }
5070                         
5071                         // camera needs no clipplane
5072                         r_refdef.view.useclipplane = false;
5073                         // TODO: is the camera origin always valid?  if so we don't need to clear this
5074                         r_refdef.view.usevieworiginculling = false;
5075
5076                         PlaneClassify(&r_refdef.view.clipplane);
5077
5078                         r_fb.water.hideplayer = false;
5079
5080                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5081                         GL_ScissorTest(false);
5082                         R_ClearScreen(r_refdef.fogenabled);
5083                         GL_ScissorTest(true);
5084                         R_View_Update();
5085                         R_AnimCache_CacheVisibleEntities();
5086                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5087
5088                         r_fb.water.hideplayer = false;
5089                         p->rt_camera = rt;
5090                 }
5091
5092         }
5093         r_fb.water.renderingscene = false;
5094         r_refdef.view = originalview;
5095         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
5096         R_View_Update();
5097         R_AnimCache_CacheVisibleEntities();
5098         goto finish;
5099 error:
5100         r_refdef.view = originalview;
5101         r_fb.water.renderingscene = false;
5102         Cvar_SetValueQuick(&r_water, 0);
5103         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5104 finish:
5105         // lowquality hack, restore cvars
5106         if (qualityreduction > 0)
5107         {
5108                 if (qualityreduction >= 1)
5109                 {
5110                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5111                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5112                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5113                 }
5114                 if (qualityreduction >= 2)
5115                 {
5116                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5117                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5118                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5119                 }
5120         }
5121 }
5122
5123 static void R_Bloom_StartFrame(void)
5124 {
5125         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5126         int viewwidth, viewheight;
5127         textype_t textype = TEXTYPE_COLORBUFFER;
5128
5129         // clear the pointers to rendertargets from last frame as they're stale
5130         r_fb.rt_screen = NULL;
5131         r_fb.rt_bloom = NULL;
5132
5133         switch (vid.renderpath)
5134         {
5135         case RENDERPATH_GL20:
5136                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5137                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5138                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5139                 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
5140                 if (!vid.support.ext_framebuffer_object)
5141                         return;
5142                 break;
5143         case RENDERPATH_GLES2:
5144                 r_fb.usedepthtextures = false;
5145                 break;
5146         }
5147
5148         if (r_viewscale_fpsscaling.integer)
5149         {
5150                 double actualframetime;
5151                 double targetframetime;
5152                 double adjust;
5153                 actualframetime = r_refdef.lastdrawscreentime;
5154                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5155                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5156                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5157                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5158                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5159                 viewscalefpsadjusted += adjust;
5160                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5161         }
5162         else
5163                 viewscalefpsadjusted = 1.0f;
5164
5165         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5166
5167         // set bloomwidth and bloomheight to the bloom resolution that will be
5168         // used (often less than the screen resolution for faster rendering)
5169         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
5170         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
5171         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
5172         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
5173         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
5174
5175         // calculate desired texture sizes
5176         screentexturewidth = viewwidth;
5177         screentextureheight = viewheight;
5178         bloomtexturewidth = r_fb.bloomwidth;
5179         bloomtextureheight = r_fb.bloomheight;
5180
5181         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))
5182         {
5183                 Cvar_SetValueQuick(&r_bloom, 0);
5184                 Cvar_SetValueQuick(&r_motionblur, 0);
5185                 Cvar_SetValueQuick(&r_damageblur, 0);
5186         }
5187
5188         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
5189         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
5190         {
5191                 if (r_fb.ghosttexture)
5192                         R_FreeTexture(r_fb.ghosttexture);
5193                 r_fb.ghosttexture = NULL;
5194
5195                 r_fb.screentexturewidth = screentexturewidth;
5196                 r_fb.screentextureheight = screentextureheight;
5197                 r_fb.textype = textype;
5198
5199                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
5200                 {
5201                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
5202                                 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);
5203                         r_fb.ghosttexture_valid = false;
5204                 }
5205         }
5206
5207         if (r_bloom.integer)
5208         {
5209                 // bloom texture is a different resolution
5210                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
5211                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5212                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
5213         }
5214         else
5215                 r_fb.bloomwidth = r_fb.bloomheight = 0;
5216
5217         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5218
5219         r_refdef.view.clear = true;
5220 }
5221
5222 static void R_Bloom_MakeTexture(void)
5223 {
5224         int x, range, dir;
5225         float xoffset, yoffset, r, brighten;
5226         float colorscale = r_bloom_colorscale.value;
5227         r_viewport_t bloomviewport;
5228         r_rendertarget_t *prev, *cur;
5229         textype_t textype = r_fb.rt_screen->colortextype[0];
5230
5231         r_refdef.stats[r_stat_bloom]++;
5232
5233         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5234
5235         // scale down screen texture to the bloom texture size
5236         CHECKGLERROR
5237         prev = r_fb.rt_screen;
5238         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5239         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5240         R_SetViewport(&bloomviewport);
5241         GL_CullFace(GL_NONE);
5242         GL_DepthTest(false);
5243         GL_BlendFunc(GL_ONE, GL_ZERO);
5244         GL_Color(colorscale, colorscale, colorscale, 1);
5245         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5246         // TODO: do boxfilter scale-down in shader?
5247         R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
5248         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5249         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5250         // we now have a properly scaled bloom image
5251
5252         // multiply bloom image by itself as many times as desired to darken it
5253         // TODO: if people actually use this it could be done more quickly in the previous shader pass
5254         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5255         {
5256                 prev = cur;
5257                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5258                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5259                 x *= 2;
5260                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
5261                 if(x <= 2)
5262                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
5263                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
5264                 GL_Color(1,1,1,1); // no fix factor supported here
5265                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5266                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
5267                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5268                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5269         }
5270
5271         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
5272         brighten = r_bloom_brighten.value;
5273         brighten = sqrt(brighten);
5274         if(range >= 1)
5275                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5276
5277         for (dir = 0;dir < 2;dir++)
5278         {
5279                 prev = cur;
5280                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5281                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5282                 // blend on at multiple vertical offsets to achieve a vertical blur
5283                 // TODO: do offset blends using GLSL
5284                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5285                 GL_BlendFunc(GL_ONE, GL_ZERO);
5286                 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
5287                 for (x = -range;x <= range;x++)
5288                 {
5289                         if (!dir){xoffset = 0;yoffset = x;}
5290                         else {xoffset = x;yoffset = 0;}
5291                         xoffset /= (float)prev->texturewidth;
5292                         yoffset /= (float)prev->textureheight;
5293                         // compute a texcoord array with the specified x and y offset
5294                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
5295                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
5296                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
5297                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
5298                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
5299                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
5300                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
5301                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
5302                         // this r value looks like a 'dot' particle, fading sharply to
5303                         // black at the edges
5304                         // (probably not realistic but looks good enough)
5305                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5306                         //r = brighten/(range*2+1);
5307                         r = brighten / (range * 2 + 1);
5308                         if(range >= 1)
5309                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
5310                         if (r <= 0)
5311                                 continue;
5312                         GL_Color(r, r, r, 1);
5313                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
5314                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5315                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5316                         GL_BlendFunc(GL_ONE, GL_ONE);
5317                 }
5318         }
5319
5320         // now we have the bloom image, so keep track of it
5321         r_fb.rt_bloom = cur;
5322 }
5323
5324 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5325 {
5326         dpuint64 permutation;
5327         float uservecs[4][4];
5328         rtexture_t *viewtexture;
5329         rtexture_t *bloomtexture;
5330
5331         R_EntityMatrix(&identitymatrix);
5332
5333         if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
5334         {
5335                 // declare variables
5336                 float blur_factor, blur_mouseaccel, blur_velocity;
5337                 static float blur_average; 
5338                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
5339
5340                 // set a goal for the factoring
5341                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
5342                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
5343                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
5344                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
5345                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
5346                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
5347
5348                 // from the goal, pick an averaged value between goal and last value
5349                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
5350                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
5351
5352                 // enforce minimum amount of blur 
5353                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
5354
5355                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
5356
5357                 // calculate values into a standard alpha
5358                 cl.motionbluralpha = 1 - exp(-
5359                                 (
5360                                         (r_motionblur.value * blur_factor / 80)
5361                                         +
5362                                         (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5363                                 )
5364                                 /
5365                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5366                                 );
5367
5368                 // randomization for the blur value to combat persistent ghosting
5369                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5370                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5371
5372                 // apply the blur
5373                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5374                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
5375                 {
5376                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5377                         GL_Color(1, 1, 1, cl.motionbluralpha);
5378                         R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
5379                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
5380                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
5381                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5382                         r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
5383                 }
5384
5385                 // updates old view angles for next pass
5386                 VectorCopy(cl.viewangles, blur_oldangles);
5387
5388                 // copy view into the ghost texture
5389                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
5390                 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
5391                 r_fb.ghosttexture_valid = true;
5392         }
5393
5394         if (r_fb.bloomwidth)
5395         {
5396                 // make the bloom texture
5397                 R_Bloom_MakeTexture();
5398         }
5399
5400 #if _MSC_VER >= 1400
5401 #define sscanf sscanf_s
5402 #endif
5403         memset(uservecs, 0, sizeof(uservecs));
5404         if (r_glsl_postprocess_uservec1_enable.integer)
5405                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5406         if (r_glsl_postprocess_uservec2_enable.integer)
5407                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5408         if (r_glsl_postprocess_uservec3_enable.integer)
5409                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5410         if (r_glsl_postprocess_uservec4_enable.integer)
5411                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5412
5413         // render to the screen fbo
5414         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5415         GL_Color(1, 1, 1, 1);
5416         GL_BlendFunc(GL_ONE, GL_ZERO);
5417
5418         viewtexture = r_fb.rt_screen->colortexture[0];
5419         bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
5420
5421         if (r_rendertarget_debug.integer >= 0)
5422         {
5423                 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
5424                 if (rt && rt->colortexture[0])
5425                 {
5426                         viewtexture = rt->colortexture[0];
5427                         bloomtexture = NULL;
5428                 }
5429         }
5430
5431         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
5432         switch(vid.renderpath)
5433         {
5434         case RENDERPATH_GL20:
5435         case RENDERPATH_GLES2:
5436                 permutation =
5437                         (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
5438                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5439                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
5440                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5441                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5442                 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5443                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
5444                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
5445                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
5446                 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]);
5447                 if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
5448                 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]);
5449                 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]);
5450                 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]);
5451                 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]);
5452                 if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5453                 if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5454                 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);
5455                 break;
5456         }
5457         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5458         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
5459 }
5460
5461 matrix4x4_t r_waterscrollmatrix;
5462
5463 void R_UpdateFog(void)
5464 {
5465         // Nehahra fog
5466         if (gamemode == GAME_NEHAHRA)
5467         {
5468                 if (gl_fogenable.integer)
5469                 {
5470                         r_refdef.oldgl_fogenable = true;
5471                         r_refdef.fog_density = gl_fogdensity.value;
5472                         r_refdef.fog_red = gl_fogred.value;
5473                         r_refdef.fog_green = gl_foggreen.value;
5474                         r_refdef.fog_blue = gl_fogblue.value;
5475                         r_refdef.fog_alpha = 1;
5476                         r_refdef.fog_start = 0;
5477                         r_refdef.fog_end = gl_skyclip.value;
5478                         r_refdef.fog_height = 1<<30;
5479                         r_refdef.fog_fadedepth = 128;
5480                 }
5481                 else if (r_refdef.oldgl_fogenable)
5482                 {
5483                         r_refdef.oldgl_fogenable = false;
5484                         r_refdef.fog_density = 0;
5485                         r_refdef.fog_red = 0;
5486                         r_refdef.fog_green = 0;
5487                         r_refdef.fog_blue = 0;
5488                         r_refdef.fog_alpha = 0;
5489                         r_refdef.fog_start = 0;
5490                         r_refdef.fog_end = 0;
5491                         r_refdef.fog_height = 1<<30;
5492                         r_refdef.fog_fadedepth = 128;
5493                 }
5494         }
5495
5496         // fog parms
5497         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5498         r_refdef.fog_start = max(0, r_refdef.fog_start);
5499         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5500
5501         if (r_refdef.fog_density && r_drawfog.integer)
5502         {
5503                 r_refdef.fogenabled = true;
5504                 // this is the point where the fog reaches 0.9986 alpha, which we
5505                 // consider a good enough cutoff point for the texture
5506                 // (0.9986 * 256 == 255.6)
5507                 if (r_fog_exp2.integer)
5508                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5509                 else
5510                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5511                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5512                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5513                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5514                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
5515                         R_BuildFogHeightTexture();
5516                 // fog color was already set
5517                 // update the fog texture
5518                 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)
5519                         R_BuildFogTexture();
5520                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
5521                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
5522         }
5523         else
5524                 r_refdef.fogenabled = false;
5525
5526         // fog color
5527         if (r_refdef.fog_density)
5528         {
5529                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5530                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5531                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5532
5533                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5534                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5535                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5536                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5537
5538                 {
5539                         vec3_t fogvec;
5540                         VectorCopy(r_refdef.fogcolor, fogvec);
5541                         //   color.rgb *= ContrastBoost * SceneBrightness;
5542                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5543                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5544                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5545                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5546                 }
5547         }
5548 }
5549
5550 void R_UpdateVariables(void)
5551 {
5552         R_Textures_Frame();
5553
5554         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
5555
5556         r_refdef.farclip = r_farclip_base.value;
5557         if (r_refdef.scene.worldmodel)
5558                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5559         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5560
5561         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5562                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5563         r_refdef.polygonfactor = 0;
5564         r_refdef.polygonoffset = 0;
5565
5566         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5567         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5568         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
5569         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5570         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5571         if (FAKELIGHT_ENABLED)
5572         {
5573                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
5574         }
5575         else if (r_refdef.scene.worldmodel)
5576         {
5577                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
5578         }
5579         if (r_showsurfaces.integer)
5580         {
5581                 r_refdef.scene.rtworld = false;
5582                 r_refdef.scene.rtworldshadows = false;
5583                 r_refdef.scene.rtdlight = false;
5584                 r_refdef.scene.rtdlightshadows = false;
5585                 r_refdef.scene.lightmapintensity = 0;
5586         }
5587
5588         r_gpuskeletal = false;
5589         switch(vid.renderpath)
5590         {
5591         case RENDERPATH_GL20:
5592                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
5593         case RENDERPATH_GLES2:
5594                 if(!vid_gammatables_trivial)
5595                 {
5596                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5597                         {
5598                                 // build GLSL gamma texture
5599 #define RAMPWIDTH 256
5600                                 unsigned short ramp[RAMPWIDTH * 3];
5601                                 unsigned char rampbgr[RAMPWIDTH][4];
5602                                 int i;
5603
5604                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5605
5606                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5607                                 for(i = 0; i < RAMPWIDTH; ++i)
5608                                 {
5609                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5610                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5611                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5612                                         rampbgr[i][3] = 0;
5613                                 }
5614                                 if (r_texture_gammaramps)
5615                                 {
5616                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
5617                                 }
5618                                 else
5619                                 {
5620                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
5621                                 }
5622                         }
5623                 }
5624                 else
5625                 {
5626                         // remove GLSL gamma texture
5627                 }
5628                 break;
5629         }
5630 }
5631
5632 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5633 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5634 /*
5635 ================
5636 R_SelectScene
5637 ================
5638 */
5639 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5640         if( scenetype != r_currentscenetype ) {
5641                 // store the old scenetype
5642                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5643                 r_currentscenetype = scenetype;
5644                 // move in the new scene
5645                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5646         }
5647 }
5648
5649 /*
5650 ================
5651 R_GetScenePointer
5652 ================
5653 */
5654 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5655 {
5656         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5657         if( scenetype == r_currentscenetype ) {
5658                 return &r_refdef.scene;
5659         } else {
5660                 return &r_scenes_store[ scenetype ];
5661         }
5662 }
5663
5664 static int R_SortEntities_Compare(const void *ap, const void *bp)
5665 {
5666         const entity_render_t *a = *(const entity_render_t **)ap;
5667         const entity_render_t *b = *(const entity_render_t **)bp;
5668
5669         // 1. compare model
5670         if(a->model < b->model)
5671                 return -1;
5672         if(a->model > b->model)
5673                 return +1;
5674
5675         // 2. compare skin
5676         // TODO possibly calculate the REAL skinnum here first using
5677         // skinscenes?
5678         if(a->skinnum < b->skinnum)
5679                 return -1;
5680         if(a->skinnum > b->skinnum)
5681                 return +1;
5682
5683         // everything we compared is equal
5684         return 0;
5685 }
5686 static void R_SortEntities(void)
5687 {
5688         // below or equal 2 ents, sorting never gains anything
5689         if(r_refdef.scene.numentities <= 2)
5690                 return;
5691         // sort
5692         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
5693 }
5694
5695 /*
5696 ================
5697 R_RenderView
5698 ================
5699 */
5700 extern cvar_t r_shadow_bouncegrid;
5701 extern cvar_t v_isometric;
5702 extern void V_MakeViewIsometric(void);
5703 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
5704 {
5705         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
5706         int viewfbo = 0;
5707         rtexture_t *viewdepthtexture = NULL;
5708         rtexture_t *viewcolortexture = NULL;
5709         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
5710
5711         // finish any 2D rendering that was queued
5712         DrawQ_Finish();
5713
5714         if (r_timereport_active)
5715                 R_TimeReport("start");
5716         r_textureframe++; // used only by R_GetCurrentTexture
5717         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5718
5719         if(R_CompileShader_CheckStaticParms())
5720                 R_GLSL_Restart_f();
5721
5722         if (!r_drawentities.integer)
5723                 r_refdef.scene.numentities = 0;
5724         else if (r_sortentities.integer)
5725                 R_SortEntities();
5726
5727         R_AnimCache_ClearCache();
5728
5729         /* adjust for stereo display */
5730         if(R_Stereo_Active())
5731         {
5732                 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);
5733                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
5734         }
5735
5736         if (r_refdef.view.isoverlay)
5737         {
5738                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5739                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
5740                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
5741                 R_TimeReport("depthclear");
5742
5743                 r_refdef.view.showdebug = false;
5744
5745                 r_fb.water.enabled = false;
5746                 r_fb.water.numwaterplanes = 0;
5747
5748                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5749
5750                 r_refdef.view.matrix = originalmatrix;
5751
5752                 CHECKGLERROR
5753                 return;
5754         }
5755
5756         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
5757         {
5758                 r_refdef.view.matrix = originalmatrix;
5759                 return;
5760         }
5761
5762         r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
5763         if (v_isometric.integer && r_refdef.view.ismain)
5764                 V_MakeViewIsometric();
5765
5766         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
5767
5768         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
5769                 // in sRGB fallback, behave similar to true sRGB: convert this
5770                 // value from linear to sRGB
5771                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
5772
5773         R_RenderView_UpdateViewVectors();
5774
5775         R_Shadow_UpdateWorldLightSelection();
5776
5777         // this will set up r_fb.rt_screen
5778         R_Bloom_StartFrame();
5779
5780         // apply bloom brightness offset
5781         if(r_fb.rt_bloom)
5782                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
5783
5784         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
5785         if (r_fb.rt_screen)
5786         {
5787                 viewfbo = r_fb.rt_screen->fbo;
5788                 viewdepthtexture = r_fb.rt_screen->depthtexture;
5789                 viewcolortexture = r_fb.rt_screen->colortexture[0];
5790                 viewx = 0;
5791                 viewy = 0;
5792                 viewwidth = width;
5793                 viewheight = height;
5794         }
5795
5796         R_Water_StartFrame();
5797
5798         CHECKGLERROR
5799         if (r_timereport_active)
5800                 R_TimeReport("viewsetup");
5801
5802         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5803
5804         // clear the whole fbo every frame - otherwise the driver will consider
5805         // it to be an inter-frame texture and stall in multi-gpu configurations
5806         if (r_fb.rt_screen)
5807                 GL_ScissorTest(false);
5808         R_ClearScreen(r_refdef.fogenabled);
5809         if (r_timereport_active)
5810                 R_TimeReport("viewclear");
5811
5812         r_refdef.view.clear = true;
5813
5814         r_refdef.view.showdebug = true;
5815
5816         R_View_Update();
5817         if (r_timereport_active)
5818                 R_TimeReport("visibility");
5819
5820         R_AnimCache_CacheVisibleEntities();
5821         if (r_timereport_active)
5822                 R_TimeReport("animcache");
5823
5824         R_Shadow_UpdateBounceGridTexture();
5825         if (r_timereport_active && r_shadow_bouncegrid.integer)
5826                 R_TimeReport("bouncegrid");
5827
5828         r_fb.water.numwaterplanes = 0;
5829         if (r_fb.water.enabled)
5830                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5831
5832         // for the actual view render we use scissoring a fair amount, so scissor
5833         // test needs to be on
5834         if (r_fb.rt_screen)
5835                 GL_ScissorTest(true);
5836         GL_Scissor(viewx, viewy, viewwidth, viewheight);
5837         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5838         r_fb.water.numwaterplanes = 0;
5839
5840         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
5841         GL_ScissorTest(false);
5842
5843         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
5844         if (r_timereport_active)
5845                 R_TimeReport("blendview");
5846
5847         r_refdef.view.matrix = originalmatrix;
5848
5849         CHECKGLERROR
5850
5851         // go back to 2d rendering
5852         DrawQ_Start();
5853 }
5854
5855 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5856 {
5857         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5858         {
5859                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5860                 if (r_timereport_active)
5861                         R_TimeReport("waterworld");
5862         }
5863
5864         // don't let sound skip if going slow
5865         if (r_refdef.scene.extraupdate)
5866                 S_ExtraUpdate ();
5867
5868         R_DrawModelsAddWaterPlanes();
5869         if (r_timereport_active)
5870                 R_TimeReport("watermodels");
5871
5872         if (r_fb.water.numwaterplanes)
5873         {
5874                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5875                 if (r_timereport_active)
5876                         R_TimeReport("waterscenes");
5877         }
5878 }
5879
5880 extern cvar_t cl_locs_show;
5881 static void R_DrawLocs(void);
5882 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
5883 static void R_DrawModelDecals(void);
5884 extern cvar_t cl_decals_newsystem;
5885 extern qboolean r_shadow_usingdeferredprepass;
5886 extern int r_shadow_shadowmapatlas_modelshadows_size;
5887 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5888 {
5889         qboolean shadowmapping = false;
5890
5891         if (r_timereport_active)
5892                 R_TimeReport("beginscene");
5893
5894         r_refdef.stats[r_stat_renders]++;
5895
5896         R_UpdateFog();
5897
5898         // don't let sound skip if going slow
5899         if (r_refdef.scene.extraupdate)
5900                 S_ExtraUpdate ();
5901
5902         R_MeshQueue_BeginScene();
5903
5904         R_SkyStartFrame();
5905
5906         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);
5907
5908         if (r_timereport_active)
5909                 R_TimeReport("skystartframe");
5910
5911         if (cl.csqc_vidvars.drawworld)
5912         {
5913                 // don't let sound skip if going slow
5914                 if (r_refdef.scene.extraupdate)
5915                         S_ExtraUpdate ();
5916
5917                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5918                 {
5919                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5920                         if (r_timereport_active)
5921                                 R_TimeReport("worldsky");
5922                 }
5923
5924                 if (R_DrawBrushModelsSky() && r_timereport_active)
5925                         R_TimeReport("bmodelsky");
5926
5927                 if (skyrendermasked && skyrenderlater)
5928                 {
5929                         // we have to force off the water clipping plane while rendering sky
5930                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5931                         R_Sky();
5932                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5933                         if (r_timereport_active)
5934                                 R_TimeReport("sky");
5935                 }
5936         }
5937
5938         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
5939         r_shadow_viewfbo = viewfbo;
5940         r_shadow_viewdepthtexture = viewdepthtexture;
5941         r_shadow_viewcolortexture = viewcolortexture;
5942         r_shadow_viewx = viewx;
5943         r_shadow_viewy = viewy;
5944         r_shadow_viewwidth = viewwidth;
5945         r_shadow_viewheight = viewheight;
5946
5947         R_Shadow_PrepareModelShadows();
5948         R_Shadow_PrepareLights();
5949         if (r_timereport_active)
5950                 R_TimeReport("preparelights");
5951
5952         // render all the shadowmaps that will be used for this view
5953         shadowmapping = R_Shadow_ShadowMappingEnabled();
5954         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
5955         {
5956                 R_Shadow_DrawShadowMaps();
5957                 if (r_timereport_active)
5958                         R_TimeReport("shadowmaps");
5959         }
5960
5961         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
5962         if (r_shadow_usingdeferredprepass)
5963                 R_Shadow_DrawPrepass();
5964
5965         // now we begin the forward pass of the view render
5966         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5967         {
5968                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5969                 if (r_timereport_active)
5970                         R_TimeReport("worlddepth");
5971         }
5972         if (r_depthfirst.integer >= 2)
5973         {
5974                 R_DrawModelsDepth();
5975                 if (r_timereport_active)
5976                         R_TimeReport("modeldepth");
5977         }
5978
5979         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5980         {
5981                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5982                 if (r_timereport_active)
5983                         R_TimeReport("world");
5984         }
5985
5986         // don't let sound skip if going slow
5987         if (r_refdef.scene.extraupdate)
5988                 S_ExtraUpdate ();
5989
5990         R_DrawModels();
5991         if (r_timereport_active)
5992                 R_TimeReport("models");
5993
5994         // don't let sound skip if going slow
5995         if (r_refdef.scene.extraupdate)
5996                 S_ExtraUpdate ();
5997
5998         if (!r_shadow_usingdeferredprepass)
5999         {
6000                 R_Shadow_DrawLights();
6001                 if (r_timereport_active)
6002                         R_TimeReport("rtlights");
6003         }
6004
6005         // don't let sound skip if going slow
6006         if (r_refdef.scene.extraupdate)
6007                 S_ExtraUpdate ();
6008
6009         if (cl.csqc_vidvars.drawworld)
6010         {
6011                 if (cl_decals_newsystem.integer)
6012                 {
6013                         R_DrawModelDecals();
6014                         if (r_timereport_active)
6015                                 R_TimeReport("modeldecals");
6016                 }
6017                 else
6018                 {
6019                         R_DrawDecals();
6020                         if (r_timereport_active)
6021                                 R_TimeReport("decals");
6022                 }
6023
6024                 R_DrawParticles();
6025                 if (r_timereport_active)
6026                         R_TimeReport("particles");
6027
6028                 R_DrawExplosions();
6029                 if (r_timereport_active)
6030                         R_TimeReport("explosions");
6031         }
6032
6033         if (r_refdef.view.showdebug)
6034         {
6035                 if (cl_locs_show.integer)
6036                 {
6037                         R_DrawLocs();
6038                         if (r_timereport_active)
6039                                 R_TimeReport("showlocs");
6040                 }
6041
6042                 if (r_drawportals.integer)
6043                 {
6044                         R_DrawPortals();
6045                         if (r_timereport_active)
6046                                 R_TimeReport("portals");
6047                 }
6048
6049                 if (r_showbboxes_client.value > 0)
6050                 {
6051                         R_DrawEntityBBoxes(CLVM_prog);
6052                         if (r_timereport_active)
6053                                 R_TimeReport("clbboxes");
6054                 }
6055                 if (r_showbboxes.value > 0)
6056                 {
6057                         R_DrawEntityBBoxes(SVVM_prog);
6058                         if (r_timereport_active)
6059                                 R_TimeReport("svbboxes");
6060                 }
6061         }
6062
6063         if (r_transparent.integer)
6064         {
6065                 R_MeshQueue_RenderTransparent();
6066                 if (r_timereport_active)
6067                         R_TimeReport("drawtrans");
6068         }
6069
6070         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))
6071         {
6072                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6073                 if (r_timereport_active)
6074                         R_TimeReport("worlddebug");
6075                 R_DrawModelsDebug();
6076                 if (r_timereport_active)
6077                         R_TimeReport("modeldebug");
6078         }
6079
6080         if (cl.csqc_vidvars.drawworld)
6081         {
6082                 R_Shadow_DrawCoronas();
6083                 if (r_timereport_active)
6084                         R_TimeReport("coronas");
6085         }
6086
6087         // don't let sound skip if going slow
6088         if (r_refdef.scene.extraupdate)
6089                 S_ExtraUpdate ();
6090 }
6091
6092 static const unsigned short bboxelements[36] =
6093 {
6094         5, 1, 3, 5, 3, 7,
6095         6, 2, 0, 6, 0, 4,
6096         7, 3, 2, 7, 2, 6,
6097         4, 0, 1, 4, 1, 5,
6098         4, 5, 7, 4, 7, 6,
6099         1, 0, 2, 1, 2, 3,
6100 };
6101
6102 #define BBOXEDGES 13
6103 static const float bboxedges[BBOXEDGES][6] = 
6104 {
6105         // whole box
6106         { 0, 0, 0, 1, 1, 1 },
6107         // bottom edges
6108         { 0, 0, 0, 0, 1, 0 },
6109         { 0, 0, 0, 1, 0, 0 },
6110         { 0, 1, 0, 1, 1, 0 },
6111         { 1, 0, 0, 1, 1, 0 },
6112         // top edges
6113         { 0, 0, 1, 0, 1, 1 },
6114         { 0, 0, 1, 1, 0, 1 },
6115         { 0, 1, 1, 1, 1, 1 },
6116         { 1, 0, 1, 1, 1, 1 },
6117         // vertical edges
6118         { 0, 0, 0, 0, 0, 1 },
6119         { 1, 0, 0, 1, 0, 1 },
6120         { 0, 1, 0, 0, 1, 1 },
6121         { 1, 1, 0, 1, 1, 1 },
6122 };
6123
6124 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6125 {
6126         int numvertices = BBOXEDGES * 8;
6127         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
6128         int numtriangles = BBOXEDGES * 12;
6129         unsigned short elements[BBOXEDGES * 36];
6130         int i, edge;
6131         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
6132
6133         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
6134
6135         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6136         GL_DepthMask(false);
6137         GL_DepthRange(0, 1);
6138         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6139
6140         for (edge = 0; edge < BBOXEDGES; edge++)
6141         {
6142                 for (i = 0; i < 3; i++)
6143                 {
6144                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
6145                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
6146                 }
6147                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
6148                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
6149                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
6150                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
6151                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
6152                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
6153                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
6154                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
6155                 for (i = 0; i < 36; i++)
6156                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
6157         }
6158         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
6159         if (r_refdef.fogenabled)
6160         {
6161                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
6162                 {
6163                         f1 = RSurf_FogVertex(v);
6164                         f2 = 1 - f1;
6165                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6166                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6167                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6168                 }
6169         }
6170         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
6171         R_Mesh_ResetTextureState();
6172         R_SetupShader_Generic_NoTexture(false, false);
6173         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
6174 }
6175
6176 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6177 {
6178         // hacky overloading of the parameters
6179         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
6180         int i;
6181         float color[4];
6182         prvm_edict_t *edict;
6183
6184         GL_CullFace(GL_NONE);
6185         R_SetupShader_Generic_NoTexture(false, false);
6186
6187         for (i = 0;i < numsurfaces;i++)
6188         {
6189                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6190                 switch ((int)PRVM_serveredictfloat(edict, solid))
6191                 {
6192                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6193                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6194                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6195                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6196                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6197                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
6198                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6199                 }
6200                 if (prog == CLVM_prog)
6201                         color[3] *= r_showbboxes_client.value;
6202                 else
6203                         color[3] *= r_showbboxes.value;
6204                 color[3] = bound(0, color[3], 1);
6205                 GL_DepthTest(!r_showdisabledepthtest.integer);
6206                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6207         }
6208 }
6209
6210 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
6211 {
6212         int i;
6213         prvm_edict_t *edict;
6214         vec3_t center;
6215
6216         if (prog == NULL)
6217                 return;
6218
6219         for (i = 0; i < prog->num_edicts; i++)
6220         {
6221                 edict = PRVM_EDICT_NUM(i);
6222                 if (edict->priv.server->free)
6223                         continue;
6224                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6225                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
6226                         continue;
6227                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
6228                         continue;
6229                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6230                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
6231         }
6232 }
6233
6234 static const int nomodelelement3i[24] =
6235 {
6236         5, 2, 0,
6237         5, 1, 2,
6238         5, 0, 3,
6239         5, 3, 1,
6240         0, 2, 4,
6241         2, 1, 4,
6242         3, 0, 4,
6243         1, 3, 4
6244 };
6245
6246 static const unsigned short nomodelelement3s[24] =
6247 {
6248         5, 2, 0,
6249         5, 1, 2,
6250         5, 0, 3,
6251         5, 3, 1,
6252         0, 2, 4,
6253         2, 1, 4,
6254         3, 0, 4,
6255         1, 3, 4
6256 };
6257
6258 static const float nomodelvertex3f[6*3] =
6259 {
6260         -16,   0,   0,
6261          16,   0,   0,
6262           0, -16,   0,
6263           0,  16,   0,
6264           0,   0, -16,
6265           0,   0,  16
6266 };
6267
6268 static const float nomodelcolor4f[6*4] =
6269 {
6270         0.0f, 0.0f, 0.5f, 1.0f,
6271         0.0f, 0.0f, 0.5f, 1.0f,
6272         0.0f, 0.5f, 0.0f, 1.0f,
6273         0.0f, 0.5f, 0.0f, 1.0f,
6274         0.5f, 0.0f, 0.0f, 1.0f,
6275         0.5f, 0.0f, 0.0f, 1.0f
6276 };
6277
6278 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6279 {
6280         int i;
6281         float f1, f2, *c;
6282         float color4f[6*4];
6283
6284         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);
6285
6286         // this is only called once per entity so numsurfaces is always 1, and
6287         // surfacelist is always {0}, so this code does not handle batches
6288
6289         if (rsurface.ent_flags & RENDER_ADDITIVE)
6290         {
6291                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6292                 GL_DepthMask(false);
6293         }
6294         else if (ent->alpha < 1)
6295         {
6296                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6297                 GL_DepthMask(false);
6298         }
6299         else
6300         {
6301                 GL_BlendFunc(GL_ONE, GL_ZERO);
6302                 GL_DepthMask(true);
6303         }
6304         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6305         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6306         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6307         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6308         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6309         for (i = 0, c = color4f;i < 6;i++, c += 4)
6310         {
6311                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
6312                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
6313                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
6314                 c[3] *= ent->alpha;
6315         }
6316         if (r_refdef.fogenabled)
6317         {
6318                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6319                 {
6320                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6321                         f2 = 1 - f1;
6322                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6323                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6324                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6325                 }
6326         }
6327 //      R_Mesh_ResetTextureState();
6328         R_SetupShader_Generic_NoTexture(false, false);
6329         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6330         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6331 }
6332
6333 void R_DrawNoModel(entity_render_t *ent)
6334 {
6335         vec3_t org;
6336         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6337         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6338                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6339         else
6340                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6341 }
6342
6343 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
6344 {
6345         vec3_t right1, right2, diff, normal;
6346
6347         VectorSubtract (org2, org1, normal);
6348
6349         // calculate 'right' vector for start
6350         VectorSubtract (r_refdef.view.origin, org1, diff);
6351         CrossProduct (normal, diff, right1);
6352         VectorNormalize (right1);
6353
6354         // calculate 'right' vector for end
6355         VectorSubtract (r_refdef.view.origin, org2, diff);
6356         CrossProduct (normal, diff, right2);
6357         VectorNormalize (right2);
6358
6359         vert[ 0] = org1[0] + width * right1[0];
6360         vert[ 1] = org1[1] + width * right1[1];
6361         vert[ 2] = org1[2] + width * right1[2];
6362         vert[ 3] = org1[0] - width * right1[0];
6363         vert[ 4] = org1[1] - width * right1[1];
6364         vert[ 5] = org1[2] - width * right1[2];
6365         vert[ 6] = org2[0] - width * right2[0];
6366         vert[ 7] = org2[1] - width * right2[1];
6367         vert[ 8] = org2[2] - width * right2[2];
6368         vert[ 9] = org2[0] + width * right2[0];
6369         vert[10] = org2[1] + width * right2[1];
6370         vert[11] = org2[2] + width * right2[2];
6371 }
6372
6373 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)
6374 {
6375         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6376         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6377         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6378         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6379         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6380         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6381         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6382         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6383         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6384         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6385         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6386         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6387 }
6388
6389 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6390 {
6391         int i;
6392         float *vertex3f;
6393         float v[3];
6394         VectorSet(v, x, y, z);
6395         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6396                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6397                         break;
6398         if (i == mesh->numvertices)
6399         {
6400                 if (mesh->numvertices < mesh->maxvertices)
6401                 {
6402                         VectorCopy(v, vertex3f);
6403                         mesh->numvertices++;
6404                 }
6405                 return mesh->numvertices;
6406         }
6407         else
6408                 return i;
6409 }
6410
6411 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6412 {
6413         int i;
6414         int *e, element[3];
6415         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6416         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6417         e = mesh->element3i + mesh->numtriangles * 3;
6418         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6419         {
6420                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6421                 if (mesh->numtriangles < mesh->maxtriangles)
6422                 {
6423                         *e++ = element[0];
6424                         *e++ = element[1];
6425                         *e++ = element[2];
6426                         mesh->numtriangles++;
6427                 }
6428                 element[1] = element[2];
6429         }
6430 }
6431
6432 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6433 {
6434         int i;
6435         int *e, element[3];
6436         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6437         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6438         e = mesh->element3i + mesh->numtriangles * 3;
6439         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6440         {
6441                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6442                 if (mesh->numtriangles < mesh->maxtriangles)
6443                 {
6444                         *e++ = element[0];
6445                         *e++ = element[1];
6446                         *e++ = element[2];
6447                         mesh->numtriangles++;
6448                 }
6449                 element[1] = element[2];
6450         }
6451 }
6452
6453 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6454 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6455 {
6456         int planenum, planenum2;
6457         int w;
6458         int tempnumpoints;
6459         mplane_t *plane, *plane2;
6460         double maxdist;
6461         double temppoints[2][256*3];
6462         // figure out how large a bounding box we need to properly compute this brush
6463         maxdist = 0;
6464         for (w = 0;w < numplanes;w++)
6465                 maxdist = max(maxdist, fabs(planes[w].dist));
6466         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6467         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6468         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6469         {
6470                 w = 0;
6471                 tempnumpoints = 4;
6472                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6473                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6474                 {
6475                         if (planenum2 == planenum)
6476                                 continue;
6477                         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);
6478                         w = !w;
6479                 }
6480                 if (tempnumpoints < 3)
6481                         continue;
6482                 // generate elements forming a triangle fan for this polygon
6483                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6484         }
6485 }
6486
6487 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)
6488 {
6489         texturelayer_t *layer;
6490         layer = t->currentlayers + t->currentnumlayers++;
6491         layer->type = type;
6492         layer->depthmask = depthmask;
6493         layer->blendfunc1 = blendfunc1;
6494         layer->blendfunc2 = blendfunc2;
6495         layer->texture = texture;
6496         layer->texmatrix = *matrix;
6497         layer->color[0] = r;
6498         layer->color[1] = g;
6499         layer->color[2] = b;
6500         layer->color[3] = a;
6501 }
6502
6503 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
6504 {
6505         if(parms[0] == 0 && parms[1] == 0)
6506                 return false;
6507         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6508                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
6509                         return false;
6510         return true;
6511 }
6512
6513 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6514 {
6515         double index, f;
6516         index = parms[2] + rsurface.shadertime * parms[3];
6517         index -= floor(index);
6518         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
6519         {
6520         default:
6521         case Q3WAVEFUNC_NONE:
6522         case Q3WAVEFUNC_NOISE:
6523         case Q3WAVEFUNC_COUNT:
6524                 f = 0;
6525                 break;
6526         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6527         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6528         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6529         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6530         case Q3WAVEFUNC_TRIANGLE:
6531                 index *= 4;
6532                 f = index - floor(index);
6533                 if (index < 1)
6534                 {
6535                         // f = f;
6536                 }
6537                 else if (index < 2)
6538                         f = 1 - f;
6539                 else if (index < 3)
6540                         f = -f;
6541                 else
6542                         f = -(1 - f);
6543                 break;
6544         }
6545         f = parms[0] + parms[1] * f;
6546         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6547                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
6548         return (float) f;
6549 }
6550
6551 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6552 {
6553         int w, h, idx;
6554         float shadertime;
6555         float f;
6556         float offsetd[2];
6557         float tcmat[12];
6558         matrix4x4_t matrix, temp;
6559         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
6560         // it's better to have one huge fixup every 9 hours than gradual
6561         // degradation over time which looks consistently bad after many hours.
6562         //
6563         // tcmod scroll in particular suffers from this degradation which can't be
6564         // effectively worked around even with floor() tricks because we don't
6565         // know if tcmod scroll is the last tcmod being applied, and for clampmap
6566         // a workaround involving floor() would be incorrect anyway...
6567         shadertime = rsurface.shadertime;
6568         if (shadertime >= 32768.0f)
6569                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
6570         switch(tcmod->tcmod)
6571         {
6572                 case Q3TCMOD_COUNT:
6573                 case Q3TCMOD_NONE:
6574                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6575                                 matrix = r_waterscrollmatrix;
6576                         else
6577                                 matrix = identitymatrix;
6578                         break;
6579                 case Q3TCMOD_ENTITYTRANSLATE:
6580                         // this is used in Q3 to allow the gamecode to control texcoord
6581                         // scrolling on the entity, which is not supported in darkplaces yet.
6582                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6583                         break;
6584                 case Q3TCMOD_ROTATE:
6585                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6586                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
6587                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6588                         break;
6589                 case Q3TCMOD_SCALE:
6590                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6591                         break;
6592                 case Q3TCMOD_SCROLL:
6593                         // this particular tcmod is a "bug for bug" compatible one with regards to
6594                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
6595                         // specifically did the wrapping and so we must mimic that...
6596                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
6597                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
6598                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
6599                         break;
6600                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6601                         w = (int) tcmod->parms[0];
6602                         h = (int) tcmod->parms[1];
6603                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
6604                         f = f - floor(f);
6605                         idx = (int) floor(f * w * h);
6606                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6607                         break;
6608                 case Q3TCMOD_STRETCH:
6609                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6610                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6611                         break;
6612                 case Q3TCMOD_TRANSFORM:
6613                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6614                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6615                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6616                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6617                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6618                         break;
6619                 case Q3TCMOD_TURBULENT:
6620                         // this is handled in the RSurf_PrepareVertices function
6621                         matrix = identitymatrix;
6622                         break;
6623         }
6624         temp = *texmatrix;
6625         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6626 }
6627
6628 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6629 {
6630         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
6631         char name[MAX_QPATH];
6632         skinframe_t *skinframe;
6633         unsigned char pixels[296*194];
6634         strlcpy(cache->name, skinname, sizeof(cache->name));
6635         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6636         if (developer_loading.integer)
6637                 Con_Printf("loading %s\n", name);
6638         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6639         if (!skinframe || !skinframe->base)
6640         {
6641                 unsigned char *f;
6642                 fs_offset_t filesize;
6643                 skinframe = NULL;
6644                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6645                 if (f)
6646                 {
6647                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
6648                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6649                         Mem_Free(f);
6650                 }
6651         }
6652         cache->skinframe = skinframe;
6653 }
6654
6655 texture_t *R_GetCurrentTexture(texture_t *t)
6656 {
6657         int i, q;
6658         const entity_render_t *ent = rsurface.entity;
6659         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
6660         q3shaderinfo_layer_tcmod_t *tcmod;
6661         float specularscale = 0.0f;
6662
6663         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
6664                 return t->currentframe;
6665         t->update_lastrenderframe = r_textureframe;
6666         t->update_lastrenderentity = (void *)ent;
6667
6668         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
6669                 t->camera_entity = ent->entitynumber;
6670         else
6671                 t->camera_entity = 0;
6672
6673         // switch to an alternate material if this is a q1bsp animated material
6674         {
6675                 texture_t *texture = t;
6676                 int s = rsurface.ent_skinnum;
6677                 if ((unsigned int)s >= (unsigned int)model->numskins)
6678                         s = 0;
6679                 if (model->skinscenes)
6680                 {
6681                         if (model->skinscenes[s].framecount > 1)
6682                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6683                         else
6684                                 s = model->skinscenes[s].firstframe;
6685                 }
6686                 if (s > 0)
6687                         t = t + s * model->num_surfaces;
6688                 if (t->animated)
6689                 {
6690                         // use an alternate animation if the entity's frame is not 0,
6691                         // and only if the texture has an alternate animation
6692                         if (t->animated == 2) // q2bsp
6693                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
6694                         else if (rsurface.ent_alttextures && t->anim_total[1])
6695                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
6696                         else
6697                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
6698                 }
6699                 texture->currentframe = t;
6700         }
6701
6702         // update currentskinframe to be a qw skin or animation frame
6703         if (rsurface.ent_qwskin >= 0)
6704         {
6705                 i = rsurface.ent_qwskin;
6706                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6707                 {
6708                         r_qwskincache_size = cl.maxclients;
6709                         if (r_qwskincache)
6710                                 Mem_Free(r_qwskincache);
6711                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6712                 }
6713                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6714                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6715                 t->currentskinframe = r_qwskincache[i].skinframe;
6716                 if (t->materialshaderpass && t->currentskinframe == NULL)
6717                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6718         }
6719         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
6720                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6721         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
6722                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
6723
6724         t->currentmaterialflags = t->basematerialflags;
6725         t->currentalpha = rsurface.entity->alpha * t->basealpha;
6726         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_water.integer || r_novis.integer || r_trippy.integer))
6727                 t->currentalpha *= r_wateralpha.value;
6728         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
6729                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
6730         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
6731                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
6732
6733         // decide on which type of lighting to use for this surface
6734         if (rsurface.entity->render_modellight_forced)
6735                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6736         if (rsurface.entity->render_rtlight_disabled)
6737                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
6738         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
6739         {
6740                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
6741                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
6742                 for (q = 0; q < 3; q++)
6743                 {
6744                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
6745                         t->render_modellight_lightdir[q] = q == 2;
6746                         t->render_modellight_ambient[q] = 1;
6747                         t->render_modellight_diffuse[q] = 0;
6748                         t->render_modellight_specular[q] = 0;
6749                         t->render_lightmap_ambient[q] = 0;
6750                         t->render_lightmap_diffuse[q] = 0;
6751                         t->render_lightmap_specular[q] = 0;
6752                         t->render_rtlight_diffuse[q] = 0;
6753                         t->render_rtlight_specular[q] = 0;
6754                 }
6755         }
6756         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
6757         {
6758                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
6759                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
6760                 for (q = 0; q < 3; q++)
6761                 {
6762                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6763                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6764                         t->render_modellight_lightdir[q] = q == 2;
6765                         t->render_modellight_diffuse[q] = 0;
6766                         t->render_modellight_specular[q] = 0;
6767                         t->render_lightmap_ambient[q] = 0;
6768                         t->render_lightmap_diffuse[q] = 0;
6769                         t->render_lightmap_specular[q] = 0;
6770                         t->render_rtlight_diffuse[q] = 0;
6771                         t->render_rtlight_specular[q] = 0;
6772                 }
6773         }
6774         else if (FAKELIGHT_ENABLED)
6775         {
6776                 // no modellight if using fakelight for the map
6777                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
6778                 for (q = 0; q < 3; q++)
6779                 {
6780                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6781                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6782                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6783                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6784                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6785                         t->render_lightmap_ambient[q] = 0;
6786                         t->render_lightmap_diffuse[q] = 0;
6787                         t->render_lightmap_specular[q] = 0;
6788                         t->render_rtlight_diffuse[q] = 0;
6789                         t->render_rtlight_specular[q] = 0;
6790                 }
6791         }
6792         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
6793         {
6794                 // ambient + single direction light (modellight)
6795                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6796                 for (q = 0; q < 3; q++)
6797                 {
6798                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6799                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6800                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6801                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6802                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6803                         t->render_lightmap_ambient[q] = 0;
6804                         t->render_lightmap_diffuse[q] = 0;
6805                         t->render_lightmap_specular[q] = 0;
6806                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6807                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6808                 }
6809         }
6810         else
6811         {
6812                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
6813                 for (q = 0; q < 3; q++)
6814                 {
6815                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6816                         t->render_modellight_lightdir[q] = q == 2;
6817                         t->render_modellight_ambient[q] = 0;
6818                         t->render_modellight_diffuse[q] = 0;
6819                         t->render_modellight_specular[q] = 0;
6820                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
6821                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
6822                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
6823                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6824                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6825                 }
6826         }
6827
6828         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
6829         {
6830                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
6831                 // attribute, we punt it to the lightmap path and hope for the best,
6832                 // but lighting doesn't work.
6833                 //
6834                 // FIXME: this is fine for effects but CSQC polygons should be subject
6835                 // to lighting.
6836                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
6837                 for (q = 0; q < 3; q++)
6838                 {
6839                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6840                         t->render_modellight_lightdir[q] = q == 2;
6841                         t->render_modellight_ambient[q] = 0;
6842                         t->render_modellight_diffuse[q] = 0;
6843                         t->render_modellight_specular[q] = 0;
6844                         t->render_lightmap_ambient[q] = 0;
6845                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6846                         t->render_lightmap_specular[q] = 0;
6847                         t->render_rtlight_diffuse[q] = 0;
6848                         t->render_rtlight_specular[q] = 0;
6849                 }
6850         }
6851
6852         for (q = 0; q < 3; q++)
6853         {
6854                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
6855                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
6856         }
6857
6858         if (rsurface.ent_flags & RENDER_ADDITIVE)
6859                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6860         else if (t->currentalpha < 1)
6861                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6862         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
6863         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6864                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
6865         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6866                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6867         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6868                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6869         if (t->backgroundshaderpass)
6870                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6871         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6872         {
6873                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
6874                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6875         }
6876         else
6877                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
6878         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
6879         {
6880                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
6881                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
6882         }
6883         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6884                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6885
6886         // there is no tcmod
6887         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6888         {
6889                 t->currenttexmatrix = r_waterscrollmatrix;
6890                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6891         }
6892         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6893         {
6894                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6895                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6896         }
6897
6898         if (t->materialshaderpass)
6899                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6900                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6901
6902         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
6903         if (t->currentskinframe->qpixels)
6904                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6905         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6906         if (!t->basetexture)
6907                 t->basetexture = r_texture_notexture;
6908         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6909         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6910         t->nmaptexture = t->currentskinframe->nmap;
6911         if (!t->nmaptexture)
6912                 t->nmaptexture = r_texture_blanknormalmap;
6913         t->glosstexture = r_texture_black;
6914         t->glowtexture = t->currentskinframe->glow;
6915         t->fogtexture = t->currentskinframe->fog;
6916         t->reflectmasktexture = t->currentskinframe->reflect;
6917         if (t->backgroundshaderpass)
6918         {
6919                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
6920                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6921                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6922                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6923                 t->backgroundglosstexture = r_texture_black;
6924                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6925                 if (!t->backgroundnmaptexture)
6926                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6927                 // make sure that if glow is going to be used, both textures are not NULL
6928                 if (!t->backgroundglowtexture && t->glowtexture)
6929                         t->backgroundglowtexture = r_texture_black;
6930                 if (!t->glowtexture && t->backgroundglowtexture)
6931                         t->glowtexture = r_texture_black;
6932         }
6933         else
6934         {
6935                 t->backgroundbasetexture = r_texture_white;
6936                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6937                 t->backgroundglosstexture = r_texture_black;
6938                 t->backgroundglowtexture = NULL;
6939         }
6940         t->specularpower = r_shadow_glossexponent.value;
6941         // TODO: store reference values for these in the texture?
6942         if (r_shadow_gloss.integer > 0)
6943         {
6944                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6945                 {
6946                         if (r_shadow_glossintensity.value > 0)
6947                         {
6948                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6949                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6950                                 specularscale = r_shadow_glossintensity.value;
6951                         }
6952                 }
6953                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6954                 {
6955                         t->glosstexture = r_texture_white;
6956                         t->backgroundglosstexture = r_texture_white;
6957                         specularscale = r_shadow_gloss2intensity.value;
6958                         t->specularpower = r_shadow_gloss2exponent.value;
6959                 }
6960         }
6961         specularscale *= t->specularscalemod;
6962         t->specularpower *= t->specularpowermod;
6963
6964         // lightmaps mode looks bad with dlights using actual texturing, so turn
6965         // off the colormap and glossmap, but leave the normalmap on as it still
6966         // accurately represents the shading involved
6967         if (gl_lightmaps.integer)
6968         {
6969                 t->basetexture = r_texture_grey128;
6970                 t->pantstexture = r_texture_black;
6971                 t->shirttexture = r_texture_black;
6972                 if (gl_lightmaps.integer < 2)
6973                         t->nmaptexture = r_texture_blanknormalmap;
6974                 t->glosstexture = r_texture_black;
6975                 t->glowtexture = NULL;
6976                 t->fogtexture = NULL;
6977                 t->reflectmasktexture = NULL;
6978                 t->backgroundbasetexture = NULL;
6979                 if (gl_lightmaps.integer < 2)
6980                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6981                 t->backgroundglosstexture = r_texture_black;
6982                 t->backgroundglowtexture = NULL;
6983                 specularscale = 0;
6984                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6985         }
6986
6987         if (specularscale != 1.0f)
6988         {
6989                 for (q = 0; q < 3; q++)
6990                 {
6991                         t->render_modellight_specular[q] *= specularscale;
6992                         t->render_lightmap_specular[q] *= specularscale;
6993                         t->render_rtlight_specular[q] *= specularscale;
6994                 }
6995         }
6996
6997         t->currentnumlayers = 0;
6998         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6999         {
7000                 int blendfunc1, blendfunc2;
7001                 qboolean depthmask;
7002                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7003                 {
7004                         blendfunc1 = GL_SRC_ALPHA;
7005                         blendfunc2 = GL_ONE;
7006                 }
7007                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7008                 {
7009                         blendfunc1 = GL_SRC_ALPHA;
7010                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7011                 }
7012                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7013                 {
7014                         blendfunc1 = t->customblendfunc[0];
7015                         blendfunc2 = t->customblendfunc[1];
7016                 }
7017                 else
7018                 {
7019                         blendfunc1 = GL_ONE;
7020                         blendfunc2 = GL_ZERO;
7021                 }
7022                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7023                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7024                 {
7025                         // basic lit geometry
7026                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
7027                         // add pants/shirt if needed
7028                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7029                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, 2 * t->render_colormap_pants[0], 2 * t->render_colormap_pants[1], 2 * t->render_colormap_pants[2], t->currentalpha);
7030                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7031                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, 2 * t->render_colormap_shirt[0], 2 * t->render_colormap_shirt[1], 2 * t->render_colormap_shirt[2], t->currentalpha);
7032                 }
7033                 else
7034                 {
7035                         // basic lit geometry
7036                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
7037                         // add pants/shirt if needed
7038                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7039                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
7040                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7041                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
7042                         // now add ambient passes if needed
7043                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
7044                         {
7045                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
7046                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7047                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
7048                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7049                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
7050                         }
7051                 }
7052                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7053                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
7054                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7055                 {
7056                         // if this is opaque use alpha blend which will darken the earlier
7057                         // passes cheaply.
7058                         //
7059                         // if this is an alpha blended material, all the earlier passes
7060                         // were darkened by fog already, so we only need to add the fog
7061                         // color ontop through the fog mask texture
7062                         //
7063                         // if this is an additive blended material, all the earlier passes
7064                         // were darkened by fog already, and we should not add fog color
7065                         // (because the background was not darkened, there is no fog color
7066                         // that was lost behind it).
7067                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
7068                 }
7069         }
7070
7071         return t;
7072 }
7073
7074 rsurfacestate_t rsurface;
7075
7076 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7077 {
7078         dp_model_t *model = ent->model;
7079         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7080         //      return;
7081         rsurface.entity = (entity_render_t *)ent;
7082         rsurface.skeleton = ent->skeleton;
7083         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7084         rsurface.ent_skinnum = ent->skinnum;
7085         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;
7086         rsurface.ent_flags = ent->flags;
7087         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
7088                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
7089         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7090         rsurface.matrix = ent->matrix;
7091         rsurface.inversematrix = ent->inversematrix;
7092         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7093         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7094         R_EntityMatrix(&rsurface.matrix);
7095         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7096         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7097         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
7098         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7099         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7100         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7101         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7102         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7103         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7104         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7105         if (ent->model->brush.submodel && !prepass)
7106         {
7107                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7108                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7109         }
7110         // if the animcache code decided it should use the shader path, skip the deform step
7111         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
7112         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
7113         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
7114         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
7115         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
7116         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
7117         {
7118                 if (ent->animcache_vertex3f)
7119                 {
7120                         r_refdef.stats[r_stat_batch_entitycache_count]++;
7121                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
7122                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
7123                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
7124                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7125                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
7126                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
7127                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7128                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
7129                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
7130                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7131                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
7132                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
7133                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7134                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
7135                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
7136                 }
7137                 else if (wanttangents)
7138                 {
7139                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7140                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7141                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7142                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7143                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7144                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7145                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7146                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7147                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7148                         rsurface.modelvertex3f_vertexbuffer = NULL;
7149                         rsurface.modelvertex3f_bufferoffset = 0;
7150                         rsurface.modelvertex3f_vertexbuffer = 0;
7151                         rsurface.modelvertex3f_bufferoffset = 0;
7152                         rsurface.modelsvector3f_vertexbuffer = 0;
7153                         rsurface.modelsvector3f_bufferoffset = 0;
7154                         rsurface.modeltvector3f_vertexbuffer = 0;
7155                         rsurface.modeltvector3f_bufferoffset = 0;
7156                         rsurface.modelnormal3f_vertexbuffer = 0;
7157                         rsurface.modelnormal3f_bufferoffset = 0;
7158                 }
7159                 else if (wantnormals)
7160                 {
7161                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7162                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7163                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7164                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7165                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7166                         rsurface.modelsvector3f = NULL;
7167                         rsurface.modeltvector3f = NULL;
7168                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7169                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7170                         rsurface.modelvertex3f_vertexbuffer = NULL;
7171                         rsurface.modelvertex3f_bufferoffset = 0;
7172                         rsurface.modelvertex3f_vertexbuffer = 0;
7173                         rsurface.modelvertex3f_bufferoffset = 0;
7174                         rsurface.modelsvector3f_vertexbuffer = 0;
7175                         rsurface.modelsvector3f_bufferoffset = 0;
7176                         rsurface.modeltvector3f_vertexbuffer = 0;
7177                         rsurface.modeltvector3f_bufferoffset = 0;
7178                         rsurface.modelnormal3f_vertexbuffer = 0;
7179                         rsurface.modelnormal3f_bufferoffset = 0;
7180                 }
7181                 else
7182                 {
7183                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7184                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7185                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7186                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7187                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7188                         rsurface.modelsvector3f = NULL;
7189                         rsurface.modeltvector3f = NULL;
7190                         rsurface.modelnormal3f = NULL;
7191                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7192                         rsurface.modelvertex3f_vertexbuffer = NULL;
7193                         rsurface.modelvertex3f_bufferoffset = 0;
7194                         rsurface.modelvertex3f_vertexbuffer = 0;
7195                         rsurface.modelvertex3f_bufferoffset = 0;
7196                         rsurface.modelsvector3f_vertexbuffer = 0;
7197                         rsurface.modelsvector3f_bufferoffset = 0;
7198                         rsurface.modeltvector3f_vertexbuffer = 0;
7199                         rsurface.modeltvector3f_bufferoffset = 0;
7200                         rsurface.modelnormal3f_vertexbuffer = 0;
7201                         rsurface.modelnormal3f_bufferoffset = 0;
7202                 }
7203                 rsurface.modelgeneratedvertex = true;
7204         }
7205         else
7206         {
7207                 if (rsurface.entityskeletaltransform3x4)
7208                 {
7209                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
7210                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
7211                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
7212                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
7213                 }
7214                 else
7215                 {
7216                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
7217                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
7218                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
7219                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
7220                 }
7221                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7222                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7223                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7224                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7225                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7226                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7227                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7228                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7229                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7230                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7231                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7232                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7233                 rsurface.modelgeneratedvertex = false;
7234         }
7235         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7236         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7237         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7238         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7239         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7240         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7241         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7242         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7243         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7244         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
7245         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7246         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
7247         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
7248         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7249         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
7250         rsurface.modelelement3i = model->surfmesh.data_element3i;
7251         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7252         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7253         rsurface.modelelement3s = model->surfmesh.data_element3s;
7254         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7255         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7256         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7257         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7258         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7259         rsurface.modelsurfaces = model->data_surfaces;
7260         rsurface.batchgeneratedvertex = false;
7261         rsurface.batchfirstvertex = 0;
7262         rsurface.batchnumvertices = 0;
7263         rsurface.batchfirsttriangle = 0;
7264         rsurface.batchnumtriangles = 0;
7265         rsurface.batchvertex3f  = NULL;
7266         rsurface.batchvertex3f_vertexbuffer = NULL;
7267         rsurface.batchvertex3f_bufferoffset = 0;
7268         rsurface.batchsvector3f = NULL;
7269         rsurface.batchsvector3f_vertexbuffer = NULL;
7270         rsurface.batchsvector3f_bufferoffset = 0;
7271         rsurface.batchtvector3f = NULL;
7272         rsurface.batchtvector3f_vertexbuffer = NULL;
7273         rsurface.batchtvector3f_bufferoffset = 0;
7274         rsurface.batchnormal3f  = NULL;
7275         rsurface.batchnormal3f_vertexbuffer = NULL;
7276         rsurface.batchnormal3f_bufferoffset = 0;
7277         rsurface.batchlightmapcolor4f = NULL;
7278         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7279         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7280         rsurface.batchtexcoordtexture2f = NULL;
7281         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7282         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7283         rsurface.batchtexcoordlightmap2f = NULL;
7284         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7285         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7286         rsurface.batchskeletalindex4ub = NULL;
7287         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7288         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7289         rsurface.batchskeletalweight4ub = NULL;
7290         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7291         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7292         rsurface.batchelement3i = NULL;
7293         rsurface.batchelement3i_indexbuffer = NULL;
7294         rsurface.batchelement3i_bufferoffset = 0;
7295         rsurface.batchelement3s = NULL;
7296         rsurface.batchelement3s_indexbuffer = NULL;
7297         rsurface.batchelement3s_bufferoffset = 0;
7298         rsurface.forcecurrenttextureupdate = false;
7299 }
7300
7301 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)
7302 {
7303         rsurface.entity = r_refdef.scene.worldentity;
7304         rsurface.skeleton = NULL;
7305         rsurface.ent_skinnum = 0;
7306         rsurface.ent_qwskin = -1;
7307         rsurface.ent_flags = entflags;
7308         rsurface.shadertime = r_refdef.scene.time - shadertime;
7309         rsurface.modelnumvertices = numvertices;
7310         rsurface.modelnumtriangles = numtriangles;
7311         rsurface.matrix = *matrix;
7312         rsurface.inversematrix = *inversematrix;
7313         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7314         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7315         R_EntityMatrix(&rsurface.matrix);
7316         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7317         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7318         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7319         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7320         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7321         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7322         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7323         rsurface.frameblend[0].lerp = 1;
7324         rsurface.ent_alttextures = false;
7325         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7326         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7327         rsurface.entityskeletaltransform3x4 = NULL;
7328         rsurface.entityskeletaltransform3x4buffer = NULL;
7329         rsurface.entityskeletaltransform3x4offset = 0;
7330         rsurface.entityskeletaltransform3x4size = 0;
7331         rsurface.entityskeletalnumtransforms = 0;
7332         r_refdef.stats[r_stat_batch_entitycustom_count]++;
7333         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
7334         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
7335         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
7336         if (wanttangents)
7337         {
7338                 rsurface.modelvertex3f = (float *)vertex3f;
7339                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7340                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7341                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7342         }
7343         else if (wantnormals)
7344         {
7345                 rsurface.modelvertex3f = (float *)vertex3f;
7346                 rsurface.modelsvector3f = NULL;
7347                 rsurface.modeltvector3f = NULL;
7348                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7349         }
7350         else
7351         {
7352                 rsurface.modelvertex3f = (float *)vertex3f;
7353                 rsurface.modelsvector3f = NULL;
7354                 rsurface.modeltvector3f = NULL;
7355                 rsurface.modelnormal3f = NULL;
7356         }
7357         rsurface.modelvertex3f_vertexbuffer = 0;
7358         rsurface.modelvertex3f_bufferoffset = 0;
7359         rsurface.modelsvector3f_vertexbuffer = 0;
7360         rsurface.modelsvector3f_bufferoffset = 0;
7361         rsurface.modeltvector3f_vertexbuffer = 0;
7362         rsurface.modeltvector3f_bufferoffset = 0;
7363         rsurface.modelnormal3f_vertexbuffer = 0;
7364         rsurface.modelnormal3f_bufferoffset = 0;
7365         rsurface.modelgeneratedvertex = true;
7366         rsurface.modellightmapcolor4f  = (float *)color4f;
7367         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7368         rsurface.modellightmapcolor4f_bufferoffset = 0;
7369         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7370         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7371         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7372         rsurface.modeltexcoordlightmap2f  = NULL;
7373         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7374         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7375         rsurface.modelskeletalindex4ub = NULL;
7376         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
7377         rsurface.modelskeletalindex4ub_bufferoffset = 0;
7378         rsurface.modelskeletalweight4ub = NULL;
7379         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
7380         rsurface.modelskeletalweight4ub_bufferoffset = 0;
7381         rsurface.modelelement3i = (int *)element3i;
7382         rsurface.modelelement3i_indexbuffer = NULL;
7383         rsurface.modelelement3i_bufferoffset = 0;
7384         rsurface.modelelement3s = (unsigned short *)element3s;
7385         rsurface.modelelement3s_indexbuffer = NULL;
7386         rsurface.modelelement3s_bufferoffset = 0;
7387         rsurface.modellightmapoffsets = NULL;
7388         rsurface.modelsurfaces = NULL;
7389         rsurface.batchgeneratedvertex = false;
7390         rsurface.batchfirstvertex = 0;
7391         rsurface.batchnumvertices = 0;
7392         rsurface.batchfirsttriangle = 0;
7393         rsurface.batchnumtriangles = 0;
7394         rsurface.batchvertex3f  = NULL;
7395         rsurface.batchvertex3f_vertexbuffer = NULL;
7396         rsurface.batchvertex3f_bufferoffset = 0;
7397         rsurface.batchsvector3f = NULL;
7398         rsurface.batchsvector3f_vertexbuffer = NULL;
7399         rsurface.batchsvector3f_bufferoffset = 0;
7400         rsurface.batchtvector3f = NULL;
7401         rsurface.batchtvector3f_vertexbuffer = NULL;
7402         rsurface.batchtvector3f_bufferoffset = 0;
7403         rsurface.batchnormal3f  = NULL;
7404         rsurface.batchnormal3f_vertexbuffer = NULL;
7405         rsurface.batchnormal3f_bufferoffset = 0;
7406         rsurface.batchlightmapcolor4f = NULL;
7407         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7408         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7409         rsurface.batchtexcoordtexture2f = NULL;
7410         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7411         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7412         rsurface.batchtexcoordlightmap2f = NULL;
7413         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7414         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7415         rsurface.batchskeletalindex4ub = NULL;
7416         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7417         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7418         rsurface.batchskeletalweight4ub = NULL;
7419         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7420         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7421         rsurface.batchelement3i = NULL;
7422         rsurface.batchelement3i_indexbuffer = NULL;
7423         rsurface.batchelement3i_bufferoffset = 0;
7424         rsurface.batchelement3s = NULL;
7425         rsurface.batchelement3s_indexbuffer = NULL;
7426         rsurface.batchelement3s_bufferoffset = 0;
7427         rsurface.forcecurrenttextureupdate = true;
7428
7429         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7430         {
7431                 if ((wantnormals || wanttangents) && !normal3f)
7432                 {
7433                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7434                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7435                 }
7436                 if (wanttangents && !svector3f)
7437                 {
7438                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7439                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7440                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7441                 }
7442         }
7443 }
7444
7445 float RSurf_FogPoint(const float *v)
7446 {
7447         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7448         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7449         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7450         float FogHeightFade = r_refdef.fogheightfade;
7451         float fogfrac;
7452         unsigned int fogmasktableindex;
7453         if (r_refdef.fogplaneviewabove)
7454                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7455         else
7456                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7457         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7458         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7459 }
7460
7461 float RSurf_FogVertex(const float *v)
7462 {
7463         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7464         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7465         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7466         float FogHeightFade = rsurface.fogheightfade;
7467         float fogfrac;
7468         unsigned int fogmasktableindex;
7469         if (r_refdef.fogplaneviewabove)
7470                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7471         else
7472                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7473         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7474         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7475 }
7476
7477 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7478 {
7479         int i;
7480         for (i = 0;i < numelements;i++)
7481                 outelement3i[i] = inelement3i[i] + adjust;
7482 }
7483
7484 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7485 extern cvar_t gl_vbo;
7486 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7487 {
7488         int deformindex;
7489         int firsttriangle;
7490         int numtriangles;
7491         int firstvertex;
7492         int endvertex;
7493         int numvertices;
7494         int surfacefirsttriangle;
7495         int surfacenumtriangles;
7496         int surfacefirstvertex;
7497         int surfaceendvertex;
7498         int surfacenumvertices;
7499         int batchnumsurfaces = texturenumsurfaces;
7500         int batchnumvertices;
7501         int batchnumtriangles;
7502         int i, j;
7503         qboolean gaps;
7504         qboolean dynamicvertex;
7505         float amplitude;
7506         float animpos;
7507         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7508         float waveparms[4];
7509         unsigned char *ub;
7510         q3shaderinfo_deform_t *deform;
7511         const msurface_t *surface, *firstsurface;
7512         if (!texturenumsurfaces)
7513                 return;
7514         // find vertex range of this surface batch
7515         gaps = false;
7516         firstsurface = texturesurfacelist[0];
7517         firsttriangle = firstsurface->num_firsttriangle;
7518         batchnumvertices = 0;
7519         batchnumtriangles = 0;
7520         firstvertex = endvertex = firstsurface->num_firstvertex;
7521         for (i = 0;i < texturenumsurfaces;i++)
7522         {
7523                 surface = texturesurfacelist[i];
7524                 if (surface != firstsurface + i)
7525                         gaps = true;
7526                 surfacefirstvertex = surface->num_firstvertex;
7527                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
7528                 surfacenumvertices = surface->num_vertices;
7529                 surfacenumtriangles = surface->num_triangles;
7530                 if (firstvertex > surfacefirstvertex)
7531                         firstvertex = surfacefirstvertex;
7532                 if (endvertex < surfaceendvertex)
7533                         endvertex = surfaceendvertex;
7534                 batchnumvertices += surfacenumvertices;
7535                 batchnumtriangles += surfacenumtriangles;
7536         }
7537
7538         r_refdef.stats[r_stat_batch_batches]++;
7539         if (gaps)
7540                 r_refdef.stats[r_stat_batch_withgaps]++;
7541         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
7542         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
7543         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
7544
7545         // we now know the vertex range used, and if there are any gaps in it
7546         rsurface.batchfirstvertex = firstvertex;
7547         rsurface.batchnumvertices = endvertex - firstvertex;
7548         rsurface.batchfirsttriangle = firsttriangle;
7549         rsurface.batchnumtriangles = batchnumtriangles;
7550
7551         // check if any dynamic vertex processing must occur
7552         dynamicvertex = false;
7553
7554         // a cvar to force the dynamic vertex path to be taken, for debugging
7555         if (r_batch_debugdynamicvertexpath.integer)
7556         {
7557                 if (!dynamicvertex)
7558                 {
7559                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
7560                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
7561                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
7562                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
7563                 }
7564                 dynamicvertex = true;
7565         }
7566
7567         // if there is a chance of animated vertex colors, it's a dynamic batch
7568         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
7569         {
7570                 if (!dynamicvertex)
7571                 {
7572                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
7573                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
7574                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
7575                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
7576                 }
7577                 dynamicvertex = true;
7578         }
7579
7580         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
7581         {
7582                 switch (deform->deform)
7583                 {
7584                 default:
7585                 case Q3DEFORM_PROJECTIONSHADOW:
7586                 case Q3DEFORM_TEXT0:
7587                 case Q3DEFORM_TEXT1:
7588                 case Q3DEFORM_TEXT2:
7589                 case Q3DEFORM_TEXT3:
7590                 case Q3DEFORM_TEXT4:
7591                 case Q3DEFORM_TEXT5:
7592                 case Q3DEFORM_TEXT6:
7593                 case Q3DEFORM_TEXT7:
7594                 case Q3DEFORM_NONE:
7595                         break;
7596                 case Q3DEFORM_AUTOSPRITE:
7597                         if (!dynamicvertex)
7598                         {
7599                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
7600                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
7601                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
7602                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
7603                         }
7604                         dynamicvertex = true;
7605                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
7606                         break;
7607                 case Q3DEFORM_AUTOSPRITE2:
7608                         if (!dynamicvertex)
7609                         {
7610                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
7611                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
7612                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
7613                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
7614                         }
7615                         dynamicvertex = true;
7616                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7617                         break;
7618                 case Q3DEFORM_NORMAL:
7619                         if (!dynamicvertex)
7620                         {
7621                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
7622                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
7623                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
7624                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
7625                         }
7626                         dynamicvertex = true;
7627                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7628                         break;
7629                 case Q3DEFORM_WAVE:
7630                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7631                                 break; // if wavefunc is a nop, ignore this transform
7632                         if (!dynamicvertex)
7633                         {
7634                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
7635                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
7636                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
7637                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
7638                         }
7639                         dynamicvertex = true;
7640                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7641                         break;
7642                 case Q3DEFORM_BULGE:
7643                         if (!dynamicvertex)
7644                         {
7645                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
7646                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
7647                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
7648                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
7649                         }
7650                         dynamicvertex = true;
7651                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7652                         break;
7653                 case Q3DEFORM_MOVE:
7654                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7655                                 break; // if wavefunc is a nop, ignore this transform
7656                         if (!dynamicvertex)
7657                         {
7658                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
7659                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
7660                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
7661                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
7662                         }
7663                         dynamicvertex = true;
7664                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7665                         break;
7666                 }
7667         }
7668         if (rsurface.texture->materialshaderpass)
7669         {
7670                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
7671                 {
7672                 default:
7673                 case Q3TCGEN_TEXTURE:
7674                         break;
7675                 case Q3TCGEN_LIGHTMAP:
7676                         if (!dynamicvertex)
7677                         {
7678                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
7679                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
7680                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
7681                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
7682                         }
7683                         dynamicvertex = true;
7684                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
7685                         break;
7686                 case Q3TCGEN_VECTOR:
7687                         if (!dynamicvertex)
7688                         {
7689                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
7690                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
7691                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
7692                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
7693                         }
7694                         dynamicvertex = true;
7695                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7696                         break;
7697                 case Q3TCGEN_ENVIRONMENT:
7698                         if (!dynamicvertex)
7699                         {
7700                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
7701                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
7702                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
7703                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
7704                         }
7705                         dynamicvertex = true;
7706                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
7707                         break;
7708                 }
7709                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7710                 {
7711                         if (!dynamicvertex)
7712                         {
7713                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
7714                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
7715                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
7716                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
7717                         }
7718                         dynamicvertex = true;
7719                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7720                 }
7721         }
7722
7723         // the caller can specify BATCHNEED_NOGAPS to force a batch with
7724         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
7725         // we ensure this by treating the vertex batch as dynamic...
7726         if ((batchneed & BATCHNEED_ALWAYSCOPY) || ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0)))
7727         {
7728                 if (!dynamicvertex)
7729                 {
7730                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
7731                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
7732                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
7733                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
7734                 }
7735                 dynamicvertex = true;
7736         }
7737
7738         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
7739         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
7740                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
7741
7742         rsurface.batchvertex3f = rsurface.modelvertex3f;
7743         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
7744         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7745         rsurface.batchsvector3f = rsurface.modelsvector3f;
7746         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
7747         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7748         rsurface.batchtvector3f = rsurface.modeltvector3f;
7749         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
7750         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7751         rsurface.batchnormal3f = rsurface.modelnormal3f;
7752         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
7753         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7754         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
7755         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
7756         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
7757         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
7758         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
7759         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7760         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7761         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
7762         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7763         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
7764         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
7765         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
7766         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
7767         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
7768         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
7769         rsurface.batchelement3i = rsurface.modelelement3i;
7770         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
7771         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
7772         rsurface.batchelement3s = rsurface.modelelement3s;
7773         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
7774         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
7775         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
7776         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
7777         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
7778         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
7779         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
7780
7781         // if any dynamic vertex processing has to occur in software, we copy the
7782         // entire surface list together before processing to rebase the vertices
7783         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
7784         //
7785         // if any gaps exist and we do not have a static vertex buffer, we have to
7786         // copy the surface list together to avoid wasting upload bandwidth on the
7787         // vertices in the gaps.
7788         //
7789         // if gaps exist and we have a static vertex buffer, we can choose whether
7790         // to combine the index buffer ranges into one dynamic index buffer or
7791         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
7792         //
7793         // in many cases the batch is reduced to one draw call.
7794
7795         rsurface.batchmultidraw = false;
7796         rsurface.batchmultidrawnumsurfaces = 0;
7797         rsurface.batchmultidrawsurfacelist = NULL;
7798
7799         if (!dynamicvertex)
7800         {
7801                 // static vertex data, just set pointers...
7802                 rsurface.batchgeneratedvertex = false;
7803                 // if there are gaps, we want to build a combined index buffer,
7804                 // otherwise use the original static buffer with an appropriate offset
7805                 if (gaps)
7806                 {
7807                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
7808                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
7809                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
7810                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
7811                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
7812                         {
7813                                 rsurface.batchmultidraw = true;
7814                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
7815                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
7816                                 return;
7817                         }
7818                         // build a new triangle elements array for this batch
7819                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7820                         rsurface.batchfirsttriangle = 0;
7821                         numtriangles = 0;
7822                         for (i = 0;i < texturenumsurfaces;i++)
7823                         {
7824                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7825                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7826                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
7827                                 numtriangles += surfacenumtriangles;
7828                         }
7829                         rsurface.batchelement3i_indexbuffer = NULL;
7830                         rsurface.batchelement3i_bufferoffset = 0;
7831                         rsurface.batchelement3s = NULL;
7832                         rsurface.batchelement3s_indexbuffer = NULL;
7833                         rsurface.batchelement3s_bufferoffset = 0;
7834                         if (endvertex <= 65536)
7835                         {
7836                                 // make a 16bit (unsigned short) index array if possible
7837                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7838                                 for (i = 0;i < numtriangles*3;i++)
7839                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7840                         }
7841                         // upload buffer data for the copytriangles batch
7842                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
7843                         {
7844                                 if (rsurface.batchelement3s)
7845                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
7846                                 else if (rsurface.batchelement3i)
7847                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
7848                         }
7849                 }
7850                 else
7851                 {
7852                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
7853                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
7854                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
7855                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
7856                 }
7857                 return;
7858         }
7859
7860         // something needs software processing, do it for real...
7861         // we only directly handle separate array data in this case and then
7862         // generate interleaved data if needed...
7863         rsurface.batchgeneratedvertex = true;
7864         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
7865         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
7866         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
7867         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
7868
7869         // now copy the vertex data into a combined array and make an index array
7870         // (this is what Quake3 does all the time)
7871         // we also apply any skeletal animation here that would have been done in
7872         // the vertex shader, because most of the dynamic vertex animation cases
7873         // need actual vertex positions and normals
7874         //if (dynamicvertex)
7875         {
7876                 rsurface.batchvertex3f = NULL;
7877                 rsurface.batchvertex3f_vertexbuffer = NULL;
7878                 rsurface.batchvertex3f_bufferoffset = 0;
7879                 rsurface.batchsvector3f = NULL;
7880                 rsurface.batchsvector3f_vertexbuffer = NULL;
7881                 rsurface.batchsvector3f_bufferoffset = 0;
7882                 rsurface.batchtvector3f = NULL;
7883                 rsurface.batchtvector3f_vertexbuffer = NULL;
7884                 rsurface.batchtvector3f_bufferoffset = 0;
7885                 rsurface.batchnormal3f = NULL;
7886                 rsurface.batchnormal3f_vertexbuffer = NULL;
7887                 rsurface.batchnormal3f_bufferoffset = 0;
7888                 rsurface.batchlightmapcolor4f = NULL;
7889                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7890                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7891                 rsurface.batchtexcoordtexture2f = NULL;
7892                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7893                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7894                 rsurface.batchtexcoordlightmap2f = NULL;
7895                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7896                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7897                 rsurface.batchskeletalindex4ub = NULL;
7898                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7899                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
7900                 rsurface.batchskeletalweight4ub = NULL;
7901                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7902                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
7903                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7904                 rsurface.batchelement3i_indexbuffer = NULL;
7905                 rsurface.batchelement3i_bufferoffset = 0;
7906                 rsurface.batchelement3s = NULL;
7907                 rsurface.batchelement3s_indexbuffer = NULL;
7908                 rsurface.batchelement3s_bufferoffset = 0;
7909                 rsurface.batchskeletaltransform3x4buffer = NULL;
7910                 rsurface.batchskeletaltransform3x4offset = 0;
7911                 rsurface.batchskeletaltransform3x4size = 0;
7912                 // we'll only be setting up certain arrays as needed
7913                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7914                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7915                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7916                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7917                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7918                 {
7919                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7920                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7921                 }
7922                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7923                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
7924                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7925                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7926                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7927                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7928                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7929                 {
7930                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7931                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7932                 }
7933                 numvertices = 0;
7934                 numtriangles = 0;
7935                 for (i = 0;i < texturenumsurfaces;i++)
7936                 {
7937                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
7938                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
7939                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7940                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7941                         // copy only the data requested
7942                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
7943                         {
7944                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7945                                 {
7946                                         if (rsurface.batchvertex3f)
7947                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7948                                         else
7949                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7950                                 }
7951                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7952                                 {
7953                                         if (rsurface.modelnormal3f)
7954                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7955                                         else
7956                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7957                                 }
7958                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7959                                 {
7960                                         if (rsurface.modelsvector3f)
7961                                         {
7962                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7963                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7964                                         }
7965                                         else
7966                                         {
7967                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7968                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7969                                         }
7970                                 }
7971                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7972                                 {
7973                                         if (rsurface.modellightmapcolor4f)
7974                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
7975                                         else
7976                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
7977                                 }
7978                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7979                                 {
7980                                         if (rsurface.modeltexcoordtexture2f)
7981                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7982                                         else
7983                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7984                                 }
7985                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7986                                 {
7987                                         if (rsurface.modeltexcoordlightmap2f)
7988                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7989                                         else
7990                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7991                                 }
7992                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7993                                 {
7994                                         if (rsurface.modelskeletalindex4ub)
7995                                         {
7996                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7997                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7998                                         }
7999                                         else
8000                                         {
8001                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
8002                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
8003                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
8004                                                 for (j = 0;j < surfacenumvertices;j++)
8005                                                         ub[j*4] = 255;
8006                                         }
8007                                 }
8008                         }
8009                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8010                         numvertices += surfacenumvertices;
8011                         numtriangles += surfacenumtriangles;
8012                 }
8013
8014                 // generate a 16bit index array as well if possible
8015                 // (in general, dynamic batches fit)
8016                 if (numvertices <= 65536)
8017                 {
8018                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8019                         for (i = 0;i < numtriangles*3;i++)
8020                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8021                 }
8022
8023                 // since we've copied everything, the batch now starts at 0
8024                 rsurface.batchfirstvertex = 0;
8025                 rsurface.batchnumvertices = batchnumvertices;
8026                 rsurface.batchfirsttriangle = 0;
8027                 rsurface.batchnumtriangles = batchnumtriangles;
8028         }
8029
8030         // apply skeletal animation that would have been done in the vertex shader
8031         if (rsurface.batchskeletaltransform3x4)
8032         {
8033                 const unsigned char *si;
8034                 const unsigned char *sw;
8035                 const float *t[4];
8036                 const float *b = rsurface.batchskeletaltransform3x4;
8037                 float *vp, *vs, *vt, *vn;
8038                 float w[4];
8039                 float m[3][4], n[3][4];
8040                 float tp[3], ts[3], tt[3], tn[3];
8041                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
8042                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
8043                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
8044                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
8045                 si = rsurface.batchskeletalindex4ub;
8046                 sw = rsurface.batchskeletalweight4ub;
8047                 vp = rsurface.batchvertex3f;
8048                 vs = rsurface.batchsvector3f;
8049                 vt = rsurface.batchtvector3f;
8050                 vn = rsurface.batchnormal3f;
8051                 memset(m[0], 0, sizeof(m));
8052                 memset(n[0], 0, sizeof(n));
8053                 for (i = 0;i < batchnumvertices;i++)
8054                 {
8055                         t[0] = b + si[0]*12;
8056                         if (sw[0] == 255)
8057                         {
8058                                 // common case - only one matrix
8059                                 m[0][0] = t[0][ 0];
8060                                 m[0][1] = t[0][ 1];
8061                                 m[0][2] = t[0][ 2];
8062                                 m[0][3] = t[0][ 3];
8063                                 m[1][0] = t[0][ 4];
8064                                 m[1][1] = t[0][ 5];
8065                                 m[1][2] = t[0][ 6];
8066                                 m[1][3] = t[0][ 7];
8067                                 m[2][0] = t[0][ 8];
8068                                 m[2][1] = t[0][ 9];
8069                                 m[2][2] = t[0][10];
8070                                 m[2][3] = t[0][11];
8071                         }
8072                         else if (sw[2] + sw[3])
8073                         {
8074                                 // blend 4 matrices
8075                                 t[1] = b + si[1]*12;
8076                                 t[2] = b + si[2]*12;
8077                                 t[3] = b + si[3]*12;
8078                                 w[0] = sw[0] * (1.0f / 255.0f);
8079                                 w[1] = sw[1] * (1.0f / 255.0f);
8080                                 w[2] = sw[2] * (1.0f / 255.0f);
8081                                 w[3] = sw[3] * (1.0f / 255.0f);
8082                                 // blend the matrices
8083                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
8084                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
8085                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
8086                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
8087                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
8088                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
8089                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
8090                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
8091                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
8092                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
8093                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
8094                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
8095                         }
8096                         else
8097                         {
8098                                 // blend 2 matrices
8099                                 t[1] = b + si[1]*12;
8100                                 w[0] = sw[0] * (1.0f / 255.0f);
8101                                 w[1] = sw[1] * (1.0f / 255.0f);
8102                                 // blend the matrices
8103                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
8104                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
8105                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
8106                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
8107                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
8108                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
8109                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
8110                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
8111                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
8112                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
8113                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
8114                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
8115                         }
8116                         si += 4;
8117                         sw += 4;
8118                         // modify the vertex
8119                         VectorCopy(vp, tp);
8120                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
8121                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
8122                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
8123                         vp += 3;
8124                         if (vn)
8125                         {
8126                                 // the normal transformation matrix is a set of cross products...
8127                                 CrossProduct(m[1], m[2], n[0]);
8128                                 CrossProduct(m[2], m[0], n[1]);
8129                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
8130                                 VectorCopy(vn, tn);
8131                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
8132                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
8133                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
8134                                 VectorNormalize(vn);
8135                                 vn += 3;
8136                                 if (vs)
8137                                 {
8138                                         VectorCopy(vs, ts);
8139                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
8140                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
8141                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
8142                                         VectorNormalize(vs);
8143                                         vs += 3;
8144                                         VectorCopy(vt, tt);
8145                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
8146                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
8147                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
8148                                         VectorNormalize(vt);
8149                                         vt += 3;
8150                                 }
8151                         }
8152                 }
8153                 rsurface.batchskeletaltransform3x4 = NULL;
8154                 rsurface.batchskeletalnumtransforms = 0;
8155         }
8156
8157         // q1bsp surfaces rendered in vertex color mode have to have colors
8158         // calculated based on lightstyles
8159         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
8160         {
8161                 // generate color arrays for the surfaces in this list
8162                 int c[4];
8163                 int scale;
8164                 int size3;
8165                 const int *offsets;
8166                 const unsigned char *lm;
8167                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8168                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8169                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8170                 numvertices = 0;
8171                 for (i = 0;i < texturenumsurfaces;i++)
8172                 {
8173                         surface = texturesurfacelist[i];
8174                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8175                         surfacenumvertices = surface->num_vertices;
8176                         if (surface->lightmapinfo->samples)
8177                         {
8178                                 for (j = 0;j < surfacenumvertices;j++)
8179                                 {
8180                                         lm = surface->lightmapinfo->samples + offsets[j];
8181                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8182                                         VectorScale(lm, scale, c);
8183                                         if (surface->lightmapinfo->styles[1] != 255)
8184                                         {
8185                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8186                                                 lm += size3;
8187                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8188                                                 VectorMA(c, scale, lm, c);
8189                                                 if (surface->lightmapinfo->styles[2] != 255)
8190                                                 {
8191                                                         lm += size3;
8192                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8193                                                         VectorMA(c, scale, lm, c);
8194                                                         if (surface->lightmapinfo->styles[3] != 255)
8195                                                         {
8196                                                                 lm += size3;
8197                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8198                                                                 VectorMA(c, scale, lm, c);
8199                                                         }
8200                                                 }
8201                                         }
8202                                         c[0] >>= 7;
8203                                         c[1] >>= 7;
8204                                         c[2] >>= 7;
8205                                         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);
8206                                         numvertices++;
8207                                 }
8208                         }
8209                         else
8210                         {
8211                                 for (j = 0;j < surfacenumvertices;j++)
8212                                 {
8213                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8214                                         numvertices++;
8215                                 }
8216                         }
8217                 }
8218         }
8219
8220         // if vertices are deformed (sprite flares and things in maps, possibly
8221         // water waves, bulges and other deformations), modify the copied vertices
8222         // in place
8223         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8224         {
8225                 float scale;
8226                 switch (deform->deform)
8227                 {
8228                 default:
8229                 case Q3DEFORM_PROJECTIONSHADOW:
8230                 case Q3DEFORM_TEXT0:
8231                 case Q3DEFORM_TEXT1:
8232                 case Q3DEFORM_TEXT2:
8233                 case Q3DEFORM_TEXT3:
8234                 case Q3DEFORM_TEXT4:
8235                 case Q3DEFORM_TEXT5:
8236                 case Q3DEFORM_TEXT6:
8237                 case Q3DEFORM_TEXT7:
8238                 case Q3DEFORM_NONE:
8239                         break;
8240                 case Q3DEFORM_AUTOSPRITE:
8241                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8242                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8243                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8244                         VectorNormalize(newforward);
8245                         VectorNormalize(newright);
8246                         VectorNormalize(newup);
8247 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8248 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8249 //                      rsurface.batchvertex3f_bufferoffset = 0;
8250 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8251 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8252 //                      rsurface.batchsvector3f_bufferoffset = 0;
8253 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8254 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8255 //                      rsurface.batchtvector3f_bufferoffset = 0;
8256 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8257 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8258 //                      rsurface.batchnormal3f_bufferoffset = 0;
8259                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8260                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8261                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8262                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8263                                 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);
8264                         // a single autosprite surface can contain multiple sprites...
8265                         for (j = 0;j < batchnumvertices - 3;j += 4)
8266                         {
8267                                 VectorClear(center);
8268                                 for (i = 0;i < 4;i++)
8269                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8270                                 VectorScale(center, 0.25f, center);
8271                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8272                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8273                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8274                                 for (i = 0;i < 4;i++)
8275                                 {
8276                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8277                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8278                                 }
8279                         }
8280                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8281                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8282                         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);
8283                         break;
8284                 case Q3DEFORM_AUTOSPRITE2:
8285                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8286                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8287                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8288                         VectorNormalize(newforward);
8289                         VectorNormalize(newright);
8290                         VectorNormalize(newup);
8291 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8292 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8293 //                      rsurface.batchvertex3f_bufferoffset = 0;
8294                         {
8295                                 const float *v1, *v2;
8296                                 vec3_t start, end;
8297                                 float f, l;
8298                                 struct
8299                                 {
8300                                         float length2;
8301                                         const float *v1;
8302                                         const float *v2;
8303                                 }
8304                                 shortest[2];
8305                                 memset(shortest, 0, sizeof(shortest));
8306                                 // a single autosprite surface can contain multiple sprites...
8307                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8308                                 {
8309                                         VectorClear(center);
8310                                         for (i = 0;i < 4;i++)
8311                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8312                                         VectorScale(center, 0.25f, center);
8313                                         // find the two shortest edges, then use them to define the
8314                                         // axis vectors for rotating around the central axis
8315                                         for (i = 0;i < 6;i++)
8316                                         {
8317                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8318                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8319                                                 l = VectorDistance2(v1, v2);
8320                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8321                                                 if (v1[2] != v2[2])
8322                                                         l += (1.0f / 1024.0f);
8323                                                 if (shortest[0].length2 > l || i == 0)
8324                                                 {
8325                                                         shortest[1] = shortest[0];
8326                                                         shortest[0].length2 = l;
8327                                                         shortest[0].v1 = v1;
8328                                                         shortest[0].v2 = v2;
8329                                                 }
8330                                                 else if (shortest[1].length2 > l || i == 1)
8331                                                 {
8332                                                         shortest[1].length2 = l;
8333                                                         shortest[1].v1 = v1;
8334                                                         shortest[1].v2 = v2;
8335                                                 }
8336                                         }
8337                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8338                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8339                                         // this calculates the right vector from the shortest edge
8340                                         // and the up vector from the edge midpoints
8341                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8342                                         VectorNormalize(right);
8343                                         VectorSubtract(end, start, up);
8344                                         VectorNormalize(up);
8345                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8346                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8347                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8348                                         VectorNegate(forward, forward);
8349                                         VectorReflect(forward, 0, up, forward);
8350                                         VectorNormalize(forward);
8351                                         CrossProduct(up, forward, newright);
8352                                         VectorNormalize(newright);
8353                                         // rotate the quad around the up axis vector, this is made
8354                                         // especially easy by the fact we know the quad is flat,
8355                                         // so we only have to subtract the center position and
8356                                         // measure distance along the right vector, and then
8357                                         // multiply that by the newright vector and add back the
8358                                         // center position
8359                                         // we also need to subtract the old position to undo the
8360                                         // displacement from the center, which we do with a
8361                                         // DotProduct, the subtraction/addition of center is also
8362                                         // optimized into DotProducts here
8363                                         l = DotProduct(right, center);
8364                                         for (i = 0;i < 4;i++)
8365                                         {
8366                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8367                                                 f = DotProduct(right, v1) - l;
8368                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8369                                         }
8370                                 }
8371                         }
8372                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8373                         {
8374 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8375 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8376 //                              rsurface.batchnormal3f_bufferoffset = 0;
8377                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8378                         }
8379                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8380                         {
8381 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8382 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8383 //                              rsurface.batchsvector3f_bufferoffset = 0;
8384 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8385 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8386 //                              rsurface.batchtvector3f_bufferoffset = 0;
8387                                 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);
8388                         }
8389                         break;
8390                 case Q3DEFORM_NORMAL:
8391                         // deform the normals to make reflections wavey
8392                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8393                         rsurface.batchnormal3f_vertexbuffer = NULL;
8394                         rsurface.batchnormal3f_bufferoffset = 0;
8395                         for (j = 0;j < batchnumvertices;j++)
8396                         {
8397                                 float vertex[3];
8398                                 float *normal = rsurface.batchnormal3f + 3*j;
8399                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8400                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8401                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8402                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8403                                 VectorNormalize(normal);
8404                         }
8405                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8406                         {
8407 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8408 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8409 //                              rsurface.batchsvector3f_bufferoffset = 0;
8410 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8411 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8412 //                              rsurface.batchtvector3f_bufferoffset = 0;
8413                                 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);
8414                         }
8415                         break;
8416                 case Q3DEFORM_WAVE:
8417                         // deform vertex array to make wavey water and flags and such
8418                         waveparms[0] = deform->waveparms[0];
8419                         waveparms[1] = deform->waveparms[1];
8420                         waveparms[2] = deform->waveparms[2];
8421                         waveparms[3] = deform->waveparms[3];
8422                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8423                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8424                         // this is how a divisor of vertex influence on deformation
8425                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8426                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8427 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8428 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8429 //                      rsurface.batchvertex3f_bufferoffset = 0;
8430 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8431 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8432 //                      rsurface.batchnormal3f_bufferoffset = 0;
8433                         for (j = 0;j < batchnumvertices;j++)
8434                         {
8435                                 // if the wavefunc depends on time, evaluate it per-vertex
8436                                 if (waveparms[3])
8437                                 {
8438                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8439                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8440                                 }
8441                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8442                         }
8443                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8444                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8445                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8446                         {
8447 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8448 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8449 //                              rsurface.batchsvector3f_bufferoffset = 0;
8450 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8451 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8452 //                              rsurface.batchtvector3f_bufferoffset = 0;
8453                                 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);
8454                         }
8455                         break;
8456                 case Q3DEFORM_BULGE:
8457                         // deform vertex array to make the surface have moving bulges
8458 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8459 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8460 //                      rsurface.batchvertex3f_bufferoffset = 0;
8461 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8462 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8463 //                      rsurface.batchnormal3f_bufferoffset = 0;
8464                         for (j = 0;j < batchnumvertices;j++)
8465                         {
8466                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8467                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8468                         }
8469                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8470                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8471                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8472                         {
8473 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8474 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8475 //                              rsurface.batchsvector3f_bufferoffset = 0;
8476 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8477 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8478 //                              rsurface.batchtvector3f_bufferoffset = 0;
8479                                 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);
8480                         }
8481                         break;
8482                 case Q3DEFORM_MOVE:
8483                         // deform vertex array
8484                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8485                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8486                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8487                         VectorScale(deform->parms, scale, waveparms);
8488 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8489 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8490 //                      rsurface.batchvertex3f_bufferoffset = 0;
8491                         for (j = 0;j < batchnumvertices;j++)
8492                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8493                         break;
8494                 }
8495         }
8496
8497         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
8498         {
8499         // generate texcoords based on the chosen texcoord source
8500                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
8501                 {
8502                 default:
8503                 case Q3TCGEN_TEXTURE:
8504                         break;
8505                 case Q3TCGEN_LIGHTMAP:
8506         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8507         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8508         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8509                         if (rsurface.batchtexcoordlightmap2f)
8510                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
8511                         break;
8512                 case Q3TCGEN_VECTOR:
8513         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8514         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8515         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8516                         for (j = 0;j < batchnumvertices;j++)
8517                         {
8518                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
8519                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
8520                         }
8521                         break;
8522                 case Q3TCGEN_ENVIRONMENT:
8523                         // make environment reflections using a spheremap
8524                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8525                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8526                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8527                         for (j = 0;j < batchnumvertices;j++)
8528                         {
8529                                 // identical to Q3A's method, but executed in worldspace so
8530                                 // carried models can be shiny too
8531
8532                                 float viewer[3], d, reflected[3], worldreflected[3];
8533
8534                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8535                                 // VectorNormalize(viewer);
8536
8537                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8538
8539                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8540                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8541                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8542                                 // note: this is proportinal to viewer, so we can normalize later
8543
8544                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8545                                 VectorNormalize(worldreflected);
8546
8547                                 // note: this sphere map only uses world x and z!
8548                                 // so positive and negative y will LOOK THE SAME.
8549                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8550                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8551                         }
8552                         break;
8553                 }
8554                 // the only tcmod that needs software vertex processing is turbulent, so
8555                 // check for it here and apply the changes if needed
8556                 // and we only support that as the first one
8557                 // (handling a mixture of turbulent and other tcmods would be problematic
8558                 //  without punting it entirely to a software path)
8559                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8560                 {
8561                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
8562                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
8563         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8564         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8565         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8566                         for (j = 0;j < batchnumvertices;j++)
8567                         {
8568                                 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);
8569                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8570                         }
8571                 }
8572         }
8573
8574         // upload buffer data for the dynamic batch
8575         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
8576         {
8577                 if (rsurface.batchvertex3f)
8578                         rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
8579                 if (rsurface.batchsvector3f)
8580                         rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
8581                 if (rsurface.batchtvector3f)
8582                         rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
8583                 if (rsurface.batchnormal3f)
8584                         rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
8585                 if (rsurface.batchlightmapcolor4f)
8586                         rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
8587                 if (rsurface.batchtexcoordtexture2f)
8588                         rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
8589                 if (rsurface.batchtexcoordlightmap2f)
8590                         rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
8591                 if (rsurface.batchskeletalindex4ub)
8592                         rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
8593                 if (rsurface.batchskeletalweight4ub)
8594                         rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
8595                 if (rsurface.batchelement3s)
8596                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
8597                 else if (rsurface.batchelement3i)
8598                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
8599         }
8600 }
8601
8602 void RSurf_DrawBatch(void)
8603 {
8604         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8605         // through the pipeline, killing it earlier in the pipeline would have
8606         // per-surface overhead rather than per-batch overhead, so it's best to
8607         // reject it here, before it hits glDraw.
8608         if (rsurface.batchnumtriangles == 0)
8609                 return;
8610 #if 0
8611         // batch debugging code
8612         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8613         {
8614                 int i;
8615                 int j;
8616                 int c;
8617                 const int *e;
8618                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8619                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8620                 {
8621                         c = e[i];
8622                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8623                         {
8624                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8625                                 {
8626                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8627                                                 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);
8628                                         break;
8629                                 }
8630                         }
8631                 }
8632         }
8633 #endif
8634         if (rsurface.batchmultidraw)
8635         {
8636                 // issue multiple draws rather than copying index data
8637                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
8638                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
8639                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
8640                 for (i = 0;i < numsurfaces;)
8641                 {
8642                         // combine consecutive surfaces as one draw
8643                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
8644                                 if (surfacelist[j] != surfacelist[k] + 1)
8645                                         break;
8646                         firstvertex = surfacelist[i]->num_firstvertex;
8647                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
8648                         firsttriangle = surfacelist[i]->num_firsttriangle;
8649                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
8650                         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);
8651                         i = j;
8652                 }
8653         }
8654         else
8655         {
8656                 // there is only one consecutive run of index data (may have been combined)
8657                 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);
8658         }
8659 }
8660
8661 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8662 {
8663         // pick the closest matching water plane
8664         int planeindex, vertexindex, bestplaneindex = -1;
8665         float d, bestd;
8666         vec3_t vert;
8667         const float *v;
8668         r_waterstate_waterplane_t *p;
8669         qboolean prepared = false;
8670         bestd = 0;
8671         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
8672         {
8673                 if(p->camera_entity != rsurface.texture->camera_entity)
8674                         continue;
8675                 d = 0;
8676                 if(!prepared)
8677                 {
8678                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
8679                         prepared = true;
8680                         if(rsurface.batchnumvertices == 0)
8681                                 break;
8682                 }
8683                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8684                 {
8685                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8686                         d += fabs(PlaneDiff(vert, &p->plane));
8687                 }
8688                 if (bestd > d || bestplaneindex < 0)
8689                 {
8690                         bestd = d;
8691                         bestplaneindex = planeindex;
8692                 }
8693         }
8694         return bestplaneindex;
8695         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8696         // this situation though, as it might be better to render single larger
8697         // batches with useless stuff (backface culled for example) than to
8698         // render multiple smaller batches
8699 }
8700
8701 void RSurf_SetupDepthAndCulling(void)
8702 {
8703         // submodels are biased to avoid z-fighting with world surfaces that they
8704         // may be exactly overlapping (avoids z-fighting artifacts on certain
8705         // doors and things in Quake maps)
8706         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8707         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8708         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8709         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8710 }
8711
8712 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8713 {
8714         int i, j;
8715         // transparent sky would be ridiculous
8716         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8717                 return;
8718         R_SetupShader_Generic_NoTexture(false, false);
8719         skyrenderlater = true;
8720         RSurf_SetupDepthAndCulling();
8721         GL_DepthMask(true);
8722
8723         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
8724         if (r_sky_scissor.integer)
8725         {
8726                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8727                 for (i = 0; i < texturenumsurfaces; i++)
8728                 {
8729                         const msurface_t *surf = texturesurfacelist[i];
8730                         const float *v;
8731                         float p[3];
8732                         float mins[3], maxs[3];
8733                         int scissor[4];
8734                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
8735                         {
8736                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
8737                                 if (j > 0)
8738                                 {
8739                                         if (mins[0] > p[0]) mins[0] = p[0];
8740                                         if (mins[1] > p[1]) mins[1] = p[1];
8741                                         if (mins[2] > p[2]) mins[2] = p[2];
8742                                         if (maxs[0] < p[0]) maxs[0] = p[0];
8743                                         if (maxs[1] < p[1]) maxs[1] = p[1];
8744                                         if (maxs[2] < p[2]) maxs[2] = p[2];
8745                                 }
8746                                 else
8747                                 {
8748                                         VectorCopy(p, mins);
8749                                         VectorCopy(p, maxs);
8750                                 }
8751                         }
8752                         if (!R_ScissorForBBox(mins, maxs, scissor))
8753                         {
8754                                 if (skyscissor[2])
8755                                 {
8756                                         if (skyscissor[0] > scissor[0])
8757                                         {
8758                                                 skyscissor[2] += skyscissor[0] - scissor[0];
8759                                                 skyscissor[0] = scissor[0];
8760                                         }
8761                                         if (skyscissor[1] > scissor[1])
8762                                         {
8763                                                 skyscissor[3] += skyscissor[1] - scissor[1];
8764                                                 skyscissor[1] = scissor[1];
8765                                         }
8766                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
8767                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
8768                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
8769                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
8770                                 }
8771                                 else
8772                                         Vector4Copy(scissor, skyscissor);
8773                         }
8774                 }
8775         }
8776
8777         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
8778         // skymasking on them, and Quake3 never did sky masking (unlike
8779         // software Quake and software Quake2), so disable the sky masking
8780         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8781         // and skymasking also looks very bad when noclipping outside the
8782         // level, so don't use it then either.
8783         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
8784         {
8785                 R_Mesh_ResetTextureState();
8786                 if (skyrendermasked)
8787                 {
8788                         R_SetupShader_DepthOrShadow(false, false, false);
8789                         // depth-only (masking)
8790                         GL_ColorMask(0, 0, 0, 0);
8791                         // just to make sure that braindead drivers don't draw
8792                         // anything despite that colormask...
8793                         GL_BlendFunc(GL_ZERO, GL_ONE);
8794                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8795                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8796                 }
8797                 else
8798                 {
8799                         R_SetupShader_Generic_NoTexture(false, false);
8800                         // fog sky
8801                         GL_BlendFunc(GL_ONE, GL_ZERO);
8802                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
8803                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8804                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
8805                 }
8806                 RSurf_DrawBatch();
8807                 if (skyrendermasked)
8808                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8809         }
8810         R_Mesh_ResetTextureState();
8811         GL_Color(1, 1, 1, 1);
8812 }
8813
8814 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8815 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8816 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8817 {
8818         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
8819                 return;
8820         if (prepass)
8821         {
8822                 // render screenspace normalmap to texture
8823                 GL_DepthMask(true);
8824                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
8825                 RSurf_DrawBatch();
8826                 return;
8827         }
8828
8829         // bind lightmap texture
8830
8831         // water/refraction/reflection/camera surfaces have to be handled specially
8832         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
8833         {
8834                 int start, end, startplaneindex;
8835                 for (start = 0;start < texturenumsurfaces;start = end)
8836                 {
8837                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
8838                         if(startplaneindex < 0)
8839                         {
8840                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
8841                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
8842                                 end = start + 1;
8843                                 continue;
8844                         }
8845                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
8846                                 ;
8847                         // now that we have a batch using the same planeindex, render it
8848                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
8849                         {
8850                                 // render water or distortion background
8851                                 GL_DepthMask(true);
8852                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8853                                 RSurf_DrawBatch();
8854                                 // blend surface on top
8855                                 GL_DepthMask(false);
8856                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
8857                                 RSurf_DrawBatch();
8858                         }
8859                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
8860                         {
8861                                 // render surface with reflection texture as input
8862                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8863                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8864                                 RSurf_DrawBatch();
8865                         }
8866                 }
8867                 return;
8868         }
8869
8870         // render surface batch normally
8871         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8872         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
8873         RSurf_DrawBatch();
8874 }
8875
8876 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8877 {
8878         int vi;
8879         int j;
8880         int texturesurfaceindex;
8881         int k;
8882         const msurface_t *surface;
8883         float surfacecolor4f[4];
8884
8885 //      R_Mesh_ResetTextureState();
8886         R_SetupShader_Generic_NoTexture(false, false);
8887
8888         GL_BlendFunc(GL_ONE, GL_ZERO);
8889         GL_DepthMask(writedepth);
8890
8891         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
8892         vi = 0;
8893         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8894         {
8895                 surface = texturesurfacelist[texturesurfaceindex];
8896                 k = (int)(((size_t)surface) / sizeof(msurface_t));
8897                 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
8898                 for (j = 0;j < surface->num_vertices;j++)
8899                 {
8900                         Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
8901                         vi++;
8902                 }
8903         }
8904         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f);
8905         RSurf_DrawBatch();
8906 }
8907
8908 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8909 {
8910         CHECKGLERROR
8911         RSurf_SetupDepthAndCulling();
8912         if (r_showsurfaces.integer && r_refdef.view.showdebug)
8913         {
8914                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
8915                 return;
8916         }
8917         switch (vid.renderpath)
8918         {
8919         case RENDERPATH_GL20:
8920         case RENDERPATH_GLES2:
8921                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8922                 break;
8923         }
8924         CHECKGLERROR
8925 }
8926
8927 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8928 {
8929         int i, j;
8930         int texturenumsurfaces, endsurface;
8931         texture_t *texture;
8932         const msurface_t *surface;
8933         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
8934
8935         RSurf_ActiveModelEntity(ent, true, true, false);
8936
8937         if (r_transparentdepthmasking.integer)
8938         {
8939                 qboolean setup = false;
8940                 for (i = 0;i < numsurfaces;i = j)
8941                 {
8942                         j = i + 1;
8943                         surface = rsurface.modelsurfaces + surfacelist[i];
8944                         texture = surface->texture;
8945                         rsurface.texture = R_GetCurrentTexture(texture);
8946                         rsurface.lightmaptexture = NULL;
8947                         rsurface.deluxemaptexture = NULL;
8948                         rsurface.uselightmaptexture = false;
8949                         // scan ahead until we find a different texture
8950                         endsurface = min(i + 1024, numsurfaces);
8951                         texturenumsurfaces = 0;
8952                         texturesurfacelist[texturenumsurfaces++] = surface;
8953                         for (;j < endsurface;j++)
8954                         {
8955                                 surface = rsurface.modelsurfaces + surfacelist[j];
8956                                 if (texture != surface->texture)
8957                                         break;
8958                                 texturesurfacelist[texturenumsurfaces++] = surface;
8959                         }
8960                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8961                                 continue;
8962                         // render the range of surfaces as depth
8963                         if (!setup)
8964                         {
8965                                 setup = true;
8966                                 GL_ColorMask(0,0,0,0);
8967                                 GL_Color(1,1,1,1);
8968                                 GL_DepthTest(true);
8969                                 GL_BlendFunc(GL_ONE, GL_ZERO);
8970                                 GL_DepthMask(true);
8971 //                              R_Mesh_ResetTextureState();
8972                         }
8973                         RSurf_SetupDepthAndCulling();
8974                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8975                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8976                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8977                         RSurf_DrawBatch();
8978                 }
8979                 if (setup)
8980                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8981         }
8982
8983         for (i = 0;i < numsurfaces;i = j)
8984         {
8985                 j = i + 1;
8986                 surface = rsurface.modelsurfaces + surfacelist[i];
8987                 texture = surface->texture;
8988                 rsurface.texture = R_GetCurrentTexture(texture);
8989                 // scan ahead until we find a different texture
8990                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
8991                 texturenumsurfaces = 0;
8992                 texturesurfacelist[texturenumsurfaces++] = surface;
8993                 if(FAKELIGHT_ENABLED)
8994                 {
8995                         rsurface.lightmaptexture = NULL;
8996                         rsurface.deluxemaptexture = NULL;
8997                         rsurface.uselightmaptexture = false;
8998                         for (;j < endsurface;j++)
8999                         {
9000                                 surface = rsurface.modelsurfaces + surfacelist[j];
9001                                 if (texture != surface->texture)
9002                                         break;
9003                                 texturesurfacelist[texturenumsurfaces++] = surface;
9004                         }
9005                 }
9006                 else
9007                 {
9008                         rsurface.lightmaptexture = surface->lightmaptexture;
9009                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9010                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9011                         for (;j < endsurface;j++)
9012                         {
9013                                 surface = rsurface.modelsurfaces + surfacelist[j];
9014                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9015                                         break;
9016                                 texturesurfacelist[texturenumsurfaces++] = surface;
9017                         }
9018                 }
9019                 // render the range of surfaces
9020                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9021         }
9022         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
9023 }
9024
9025 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9026 {
9027         // transparent surfaces get pushed off into the transparent queue
9028         int surfacelistindex;
9029         const msurface_t *surface;
9030         vec3_t tempcenter, center;
9031         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9032         {
9033                 surface = texturesurfacelist[surfacelistindex];
9034                 if (r_transparent_sortsurfacesbynearest.integer)
9035                 {
9036                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
9037                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
9038                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
9039                 }
9040                 else
9041                 {
9042                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9043                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9044                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9045                 }
9046                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9047                 if (rsurface.entity->transparent_offset) // transparent offset
9048                 {
9049                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
9050                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
9051                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
9052                 }
9053                 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);
9054         }
9055 }
9056
9057 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9058 {
9059         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9060                 return;
9061         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9062                 return;
9063         RSurf_SetupDepthAndCulling();
9064         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
9065         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9066         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
9067         RSurf_DrawBatch();
9068 }
9069
9070 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9071 {
9072         CHECKGLERROR
9073         if (depthonly)
9074                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9075         else if (prepass)
9076         {
9077                 if (!rsurface.texture->currentnumlayers)
9078                         return;
9079                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9080                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
9081                 else
9082                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9083         }
9084         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
9085                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9086         else if (!rsurface.texture->currentnumlayers)
9087                 return;
9088         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
9089         {
9090                 // in the deferred case, transparent surfaces were queued during prepass
9091                 if (!r_shadow_usingdeferredprepass)
9092                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
9093         }
9094         else
9095         {
9096                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9097                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9098         }
9099         CHECKGLERROR
9100 }
9101
9102 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9103 {
9104         int i, j;
9105         texture_t *texture;
9106         R_FrameData_SetMark();
9107         // break the surface list down into batches by texture and use of lightmapping
9108         for (i = 0;i < numsurfaces;i = j)
9109         {
9110                 j = i + 1;
9111                 // texture is the base texture pointer, rsurface.texture is the
9112                 // current frame/skin the texture is directing us to use (for example
9113                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9114                 // use skin 1 instead)
9115                 texture = surfacelist[i]->texture;
9116                 rsurface.texture = R_GetCurrentTexture(texture);
9117                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9118                 {
9119                         // if this texture is not the kind we want, skip ahead to the next one
9120                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9121                                 ;
9122                         continue;
9123                 }
9124                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9125                 {
9126                         rsurface.lightmaptexture = NULL;
9127                         rsurface.deluxemaptexture = NULL;
9128                         rsurface.uselightmaptexture = false;
9129                         // simply scan ahead until we find a different texture or lightmap state
9130                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9131                                 ;
9132                 }
9133                 else
9134                 {
9135                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9136                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9137                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9138                         // simply scan ahead until we find a different texture or lightmap state
9139                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9140                                 ;
9141                 }
9142                 // render the range of surfaces
9143                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9144         }
9145         R_FrameData_ReturnToMark();
9146 }
9147
9148 float locboxvertex3f[6*4*3] =
9149 {
9150         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9151         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9152         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9153         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9154         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9155         1,0,0, 0,0,0, 0,1,0, 1,1,0
9156 };
9157
9158 unsigned short locboxelements[6*2*3] =
9159 {
9160          0, 1, 2, 0, 2, 3,
9161          4, 5, 6, 4, 6, 7,
9162          8, 9,10, 8,10,11,
9163         12,13,14, 12,14,15,
9164         16,17,18, 16,18,19,
9165         20,21,22, 20,22,23
9166 };
9167
9168 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9169 {
9170         int i, j;
9171         cl_locnode_t *loc = (cl_locnode_t *)ent;
9172         vec3_t mins, size;
9173         float vertex3f[6*4*3];
9174         CHECKGLERROR
9175         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9176         GL_DepthMask(false);
9177         GL_DepthRange(0, 1);
9178         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9179         GL_DepthTest(true);
9180         GL_CullFace(GL_NONE);
9181         R_EntityMatrix(&identitymatrix);
9182
9183 //      R_Mesh_ResetTextureState();
9184
9185         i = surfacelist[0];
9186         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9187                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9188                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9189                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9190
9191         if (VectorCompare(loc->mins, loc->maxs))
9192         {
9193                 VectorSet(size, 2, 2, 2);
9194                 VectorMA(loc->mins, -0.5f, size, mins);
9195         }
9196         else
9197         {
9198                 VectorCopy(loc->mins, mins);
9199                 VectorSubtract(loc->maxs, loc->mins, size);
9200         }
9201
9202         for (i = 0;i < 6*4*3;)
9203                 for (j = 0;j < 3;j++, i++)
9204                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9205
9206         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
9207         R_SetupShader_Generic_NoTexture(false, false);
9208         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
9209 }
9210
9211 void R_DrawLocs(void)
9212 {
9213         int index;
9214         cl_locnode_t *loc, *nearestloc;
9215         vec3_t center;
9216         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9217         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9218         {
9219                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9220                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9221         }
9222 }
9223
9224 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9225 {
9226         if (decalsystem->decals)
9227                 Mem_Free(decalsystem->decals);
9228         memset(decalsystem, 0, sizeof(*decalsystem));
9229 }
9230
9231 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)
9232 {
9233         tridecal_t *decal;
9234         tridecal_t *decals;
9235         int i;
9236
9237         // expand or initialize the system
9238         if (decalsystem->maxdecals <= decalsystem->numdecals)
9239         {
9240                 decalsystem_t old = *decalsystem;
9241                 qboolean useshortelements;
9242                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9243                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9244                 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)));
9245                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9246                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9247                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9248                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9249                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9250                 if (decalsystem->numdecals)
9251                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9252                 if (old.decals)
9253                         Mem_Free(old.decals);
9254                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9255                         decalsystem->element3i[i] = i;
9256                 if (useshortelements)
9257                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9258                                 decalsystem->element3s[i] = i;
9259         }
9260
9261         // grab a decal and search for another free slot for the next one
9262         decals = decalsystem->decals;
9263         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9264         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
9265                 ;
9266         decalsystem->freedecal = i;
9267         if (decalsystem->numdecals <= i)
9268                 decalsystem->numdecals = i + 1;
9269
9270         // initialize the decal
9271         decal->lived = 0;
9272         decal->triangleindex = triangleindex;
9273         decal->surfaceindex = surfaceindex;
9274         decal->decalsequence = decalsequence;
9275         decal->color4f[0][0] = c0[0];
9276         decal->color4f[0][1] = c0[1];
9277         decal->color4f[0][2] = c0[2];
9278         decal->color4f[0][3] = 1;
9279         decal->color4f[1][0] = c1[0];
9280         decal->color4f[1][1] = c1[1];
9281         decal->color4f[1][2] = c1[2];
9282         decal->color4f[1][3] = 1;
9283         decal->color4f[2][0] = c2[0];
9284         decal->color4f[2][1] = c2[1];
9285         decal->color4f[2][2] = c2[2];
9286         decal->color4f[2][3] = 1;
9287         decal->vertex3f[0][0] = v0[0];
9288         decal->vertex3f[0][1] = v0[1];
9289         decal->vertex3f[0][2] = v0[2];
9290         decal->vertex3f[1][0] = v1[0];
9291         decal->vertex3f[1][1] = v1[1];
9292         decal->vertex3f[1][2] = v1[2];
9293         decal->vertex3f[2][0] = v2[0];
9294         decal->vertex3f[2][1] = v2[1];
9295         decal->vertex3f[2][2] = v2[2];
9296         decal->texcoord2f[0][0] = t0[0];
9297         decal->texcoord2f[0][1] = t0[1];
9298         decal->texcoord2f[1][0] = t1[0];
9299         decal->texcoord2f[1][1] = t1[1];
9300         decal->texcoord2f[2][0] = t2[0];
9301         decal->texcoord2f[2][1] = t2[1];
9302         TriangleNormal(v0, v1, v2, decal->plane);
9303         VectorNormalize(decal->plane);
9304         decal->plane[3] = DotProduct(v0, decal->plane);
9305 }
9306
9307 extern cvar_t cl_decals_bias;
9308 extern cvar_t cl_decals_models;
9309 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9310 // baseparms, parms, temps
9311 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)
9312 {
9313         int cornerindex;
9314         int index;
9315         float v[9][3];
9316         const float *vertex3f;
9317         const float *normal3f;
9318         int numpoints;
9319         float points[2][9][3];
9320         float temp[3];
9321         float tc[9][2];
9322         float f;
9323         float c[9][4];
9324         const int *e;
9325
9326         e = rsurface.modelelement3i + 3*triangleindex;
9327
9328         vertex3f = rsurface.modelvertex3f;
9329         normal3f = rsurface.modelnormal3f;
9330
9331         if (normal3f)
9332         {
9333                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9334                 {
9335                         index = 3*e[cornerindex];
9336                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
9337                 }
9338         }
9339         else
9340         {
9341                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9342                 {
9343                         index = 3*e[cornerindex];
9344                         VectorCopy(vertex3f + index, v[cornerindex]);
9345                 }
9346         }
9347
9348         // cull backfaces
9349         //TriangleNormal(v[0], v[1], v[2], normal);
9350         //if (DotProduct(normal, localnormal) < 0.0f)
9351         //      continue;
9352         // clip by each of the box planes formed from the projection matrix
9353         // if anything survives, we emit the decal
9354         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]);
9355         if (numpoints < 3)
9356                 return;
9357         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]);
9358         if (numpoints < 3)
9359                 return;
9360         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]);
9361         if (numpoints < 3)
9362                 return;
9363         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]);
9364         if (numpoints < 3)
9365                 return;
9366         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]);
9367         if (numpoints < 3)
9368                 return;
9369         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]);
9370         if (numpoints < 3)
9371                 return;
9372         // some part of the triangle survived, so we have to accept it...
9373         if (dynamic)
9374         {
9375                 // dynamic always uses the original triangle
9376                 numpoints = 3;
9377                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9378                 {
9379                         index = 3*e[cornerindex];
9380                         VectorCopy(vertex3f + index, v[cornerindex]);
9381                 }
9382         }
9383         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9384         {
9385                 // convert vertex positions to texcoords
9386                 Matrix4x4_Transform(projection, v[cornerindex], temp);
9387                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9388                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9389                 // calculate distance fade from the projection origin
9390                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9391                 f = bound(0.0f, f, 1.0f);
9392                 c[cornerindex][0] = r * f;
9393                 c[cornerindex][1] = g * f;
9394                 c[cornerindex][2] = b * f;
9395                 c[cornerindex][3] = 1.0f;
9396                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9397         }
9398         if (dynamic)
9399                 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);
9400         else
9401                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9402                         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);
9403 }
9404 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)
9405 {
9406         matrix4x4_t projection;
9407         decalsystem_t *decalsystem;
9408         qboolean dynamic;
9409         dp_model_t *model;
9410         const msurface_t *surface;
9411         const msurface_t *surfaces;
9412         const int *surfacelist;
9413         const texture_t *texture;
9414         int numtriangles;
9415         int numsurfacelist;
9416         int surfacelistindex;
9417         int surfaceindex;
9418         int triangleindex;
9419         float localorigin[3];
9420         float localnormal[3];
9421         float localmins[3];
9422         float localmaxs[3];
9423         float localsize;
9424         //float normal[3];
9425         float planes[6][4];
9426         float angles[3];
9427         bih_t *bih;
9428         int bih_triangles_count;
9429         int bih_triangles[256];
9430         int bih_surfaces[256];
9431
9432         decalsystem = &ent->decalsystem;
9433         model = ent->model;
9434         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9435         {
9436                 R_DecalSystem_Reset(&ent->decalsystem);
9437                 return;
9438         }
9439
9440         if (!model->brush.data_leafs && !cl_decals_models.integer)
9441         {
9442                 if (decalsystem->model)
9443                         R_DecalSystem_Reset(decalsystem);
9444                 return;
9445         }
9446
9447         if (decalsystem->model != model)
9448                 R_DecalSystem_Reset(decalsystem);
9449         decalsystem->model = model;
9450
9451         RSurf_ActiveModelEntity(ent, true, false, false);
9452
9453         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9454         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9455         VectorNormalize(localnormal);
9456         localsize = worldsize*rsurface.inversematrixscale;
9457         localmins[0] = localorigin[0] - localsize;
9458         localmins[1] = localorigin[1] - localsize;
9459         localmins[2] = localorigin[2] - localsize;
9460         localmaxs[0] = localorigin[0] + localsize;
9461         localmaxs[1] = localorigin[1] + localsize;
9462         localmaxs[2] = localorigin[2] + localsize;
9463
9464         //VectorCopy(localnormal, planes[4]);
9465         //VectorVectors(planes[4], planes[2], planes[0]);
9466         AnglesFromVectors(angles, localnormal, NULL, false);
9467         AngleVectors(angles, planes[0], planes[2], planes[4]);
9468         VectorNegate(planes[0], planes[1]);
9469         VectorNegate(planes[2], planes[3]);
9470         VectorNegate(planes[4], planes[5]);
9471         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9472         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9473         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9474         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9475         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9476         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9477
9478 #if 1
9479 // works
9480 {
9481         matrix4x4_t forwardprojection;
9482         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9483         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9484 }
9485 #else
9486 // broken
9487 {
9488         float projectionvector[4][3];
9489         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9490         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9491         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9492         projectionvector[0][0] = planes[0][0] * ilocalsize;
9493         projectionvector[0][1] = planes[1][0] * ilocalsize;
9494         projectionvector[0][2] = planes[2][0] * ilocalsize;
9495         projectionvector[1][0] = planes[0][1] * ilocalsize;
9496         projectionvector[1][1] = planes[1][1] * ilocalsize;
9497         projectionvector[1][2] = planes[2][1] * ilocalsize;
9498         projectionvector[2][0] = planes[0][2] * ilocalsize;
9499         projectionvector[2][1] = planes[1][2] * ilocalsize;
9500         projectionvector[2][2] = planes[2][2] * ilocalsize;
9501         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9502         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9503         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9504         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9505 }
9506 #endif
9507
9508         dynamic = model->surfmesh.isanimated;
9509         numsurfacelist = model->nummodelsurfaces;
9510         surfacelist = model->sortedmodelsurfaces;
9511         surfaces = model->data_surfaces;
9512
9513         bih = NULL;
9514         bih_triangles_count = -1;
9515         if(!dynamic)
9516         {
9517                 if(model->render_bih.numleafs)
9518                         bih = &model->render_bih;
9519                 else if(model->collision_bih.numleafs)
9520                         bih = &model->collision_bih;
9521         }
9522         if(bih)
9523                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
9524         if(bih_triangles_count == 0)
9525                 return;
9526         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
9527                 return;
9528         if(bih_triangles_count > 0)
9529         {
9530                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
9531                 {
9532                         surfaceindex = bih_surfaces[triangleindex];
9533                         surface = surfaces + surfaceindex;
9534                         texture = surface->texture;
9535                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9536                                 continue;
9537                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9538                                 continue;
9539                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
9540                 }
9541         }
9542         else
9543         {
9544                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9545                 {
9546                         surfaceindex = surfacelist[surfacelistindex];
9547                         surface = surfaces + surfaceindex;
9548                         // check cull box first because it rejects more than any other check
9549                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9550                                 continue;
9551                         // skip transparent surfaces
9552                         texture = surface->texture;
9553                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9554                                 continue;
9555                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9556                                 continue;
9557                         numtriangles = surface->num_triangles;
9558                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
9559                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
9560                 }
9561         }
9562 }
9563
9564 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9565 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)
9566 {
9567         int renderentityindex;
9568         float worldmins[3];
9569         float worldmaxs[3];
9570         entity_render_t *ent;
9571
9572         if (!cl_decals_newsystem.integer)
9573                 return;
9574
9575         worldmins[0] = worldorigin[0] - worldsize;
9576         worldmins[1] = worldorigin[1] - worldsize;
9577         worldmins[2] = worldorigin[2] - worldsize;
9578         worldmaxs[0] = worldorigin[0] + worldsize;
9579         worldmaxs[1] = worldorigin[1] + worldsize;
9580         worldmaxs[2] = worldorigin[2] + worldsize;
9581
9582         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9583
9584         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9585         {
9586                 ent = r_refdef.scene.entities[renderentityindex];
9587                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9588                         continue;
9589
9590                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9591         }
9592 }
9593
9594 typedef struct r_decalsystem_splatqueue_s
9595 {
9596         vec3_t worldorigin;
9597         vec3_t worldnormal;
9598         float color[4];
9599         float tcrange[4];
9600         float worldsize;
9601         unsigned int decalsequence;
9602 }
9603 r_decalsystem_splatqueue_t;
9604
9605 int r_decalsystem_numqueued = 0;
9606 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9607
9608 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)
9609 {
9610         r_decalsystem_splatqueue_t *queue;
9611
9612         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9613                 return;
9614
9615         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9616         VectorCopy(worldorigin, queue->worldorigin);
9617         VectorCopy(worldnormal, queue->worldnormal);
9618         Vector4Set(queue->color, r, g, b, a);
9619         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9620         queue->worldsize = worldsize;
9621         queue->decalsequence = cl.decalsequence++;
9622 }
9623
9624 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9625 {
9626         int i;
9627         r_decalsystem_splatqueue_t *queue;
9628
9629         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9630                 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);
9631         r_decalsystem_numqueued = 0;
9632 }
9633
9634 extern cvar_t cl_decals_max;
9635 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9636 {
9637         int i;
9638         decalsystem_t *decalsystem = &ent->decalsystem;
9639         int numdecals;
9640         unsigned int killsequence;
9641         tridecal_t *decal;
9642         float frametime;
9643         float lifetime;
9644
9645         if (!decalsystem->numdecals)
9646                 return;
9647
9648         if (r_showsurfaces.integer)
9649                 return;
9650
9651         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9652         {
9653                 R_DecalSystem_Reset(decalsystem);
9654                 return;
9655         }
9656
9657         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
9658         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9659
9660         if (decalsystem->lastupdatetime)
9661                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
9662         else
9663                 frametime = 0;
9664         decalsystem->lastupdatetime = r_refdef.scene.time;
9665         numdecals = decalsystem->numdecals;
9666
9667         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9668         {
9669                 if (decal->color4f[0][3])
9670                 {
9671                         decal->lived += frametime;
9672                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
9673                         {
9674                                 memset(decal, 0, sizeof(*decal));
9675                                 if (decalsystem->freedecal > i)
9676                                         decalsystem->freedecal = i;
9677                         }
9678                 }
9679         }
9680         decal = decalsystem->decals;
9681         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
9682                 numdecals--;
9683
9684         // collapse the array by shuffling the tail decals into the gaps
9685         for (;;)
9686         {
9687                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
9688                         decalsystem->freedecal++;
9689                 if (decalsystem->freedecal == numdecals)
9690                         break;
9691                 decal[decalsystem->freedecal] = decal[--numdecals];
9692         }
9693
9694         decalsystem->numdecals = numdecals;
9695
9696         if (numdecals <= 0)
9697         {
9698                 // if there are no decals left, reset decalsystem
9699                 R_DecalSystem_Reset(decalsystem);
9700         }
9701 }
9702
9703 extern skinframe_t *decalskinframe;
9704 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9705 {
9706         int i;
9707         decalsystem_t *decalsystem = &ent->decalsystem;
9708         int numdecals;
9709         tridecal_t *decal;
9710         float faderate;
9711         float alpha;
9712         float *v3f;
9713         float *c4f;
9714         float *t2f;
9715         const int *e;
9716         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9717         int numtris = 0;
9718
9719         numdecals = decalsystem->numdecals;
9720         if (!numdecals)
9721                 return;
9722
9723         if (r_showsurfaces.integer)
9724                 return;
9725
9726         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9727         {
9728                 R_DecalSystem_Reset(decalsystem);
9729                 return;
9730         }
9731
9732         // if the model is static it doesn't matter what value we give for
9733         // wantnormals and wanttangents, so this logic uses only rules applicable
9734         // to a model, knowing that they are meaningless otherwise
9735         RSurf_ActiveModelEntity(ent, false, false, false);
9736
9737         decalsystem->lastupdatetime = r_refdef.scene.time;
9738
9739         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9740
9741         // update vertex positions for animated models
9742         v3f = decalsystem->vertex3f;
9743         c4f = decalsystem->color4f;
9744         t2f = decalsystem->texcoord2f;
9745         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9746         {
9747                 if (!decal->color4f[0][3])
9748                         continue;
9749
9750                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9751                         continue;
9752
9753                 // skip backfaces
9754                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
9755                         continue;
9756
9757                 // update color values for fading decals
9758                 if (decal->lived >= cl_decals_time.value)
9759                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9760                 else
9761                         alpha = 1.0f;
9762
9763                 c4f[ 0] = decal->color4f[0][0] * alpha;
9764                 c4f[ 1] = decal->color4f[0][1] * alpha;
9765                 c4f[ 2] = decal->color4f[0][2] * alpha;
9766                 c4f[ 3] = 1;
9767                 c4f[ 4] = decal->color4f[1][0] * alpha;
9768                 c4f[ 5] = decal->color4f[1][1] * alpha;
9769                 c4f[ 6] = decal->color4f[1][2] * alpha;
9770                 c4f[ 7] = 1;
9771                 c4f[ 8] = decal->color4f[2][0] * alpha;
9772                 c4f[ 9] = decal->color4f[2][1] * alpha;
9773                 c4f[10] = decal->color4f[2][2] * alpha;
9774                 c4f[11] = 1;
9775
9776                 t2f[0] = decal->texcoord2f[0][0];
9777                 t2f[1] = decal->texcoord2f[0][1];
9778                 t2f[2] = decal->texcoord2f[1][0];
9779                 t2f[3] = decal->texcoord2f[1][1];
9780                 t2f[4] = decal->texcoord2f[2][0];
9781                 t2f[5] = decal->texcoord2f[2][1];
9782
9783                 // update vertex positions for animated models
9784                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
9785                 {
9786                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9787                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
9788                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
9789                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
9790                 }
9791                 else
9792                 {
9793                         VectorCopy(decal->vertex3f[0], v3f);
9794                         VectorCopy(decal->vertex3f[1], v3f + 3);
9795                         VectorCopy(decal->vertex3f[2], v3f + 6);
9796                 }
9797
9798                 if (r_refdef.fogenabled)
9799                 {
9800                         alpha = RSurf_FogVertex(v3f);
9801                         VectorScale(c4f, alpha, c4f);
9802                         alpha = RSurf_FogVertex(v3f + 3);
9803                         VectorScale(c4f + 4, alpha, c4f + 4);
9804                         alpha = RSurf_FogVertex(v3f + 6);
9805                         VectorScale(c4f + 8, alpha, c4f + 8);
9806                 }
9807
9808                 v3f += 9;
9809                 c4f += 12;
9810                 t2f += 6;
9811                 numtris++;
9812         }
9813
9814         if (numtris > 0)
9815         {
9816                 r_refdef.stats[r_stat_drawndecals] += numtris;
9817
9818                 // now render the decals all at once
9819                 // (this assumes they all use one particle font texture!)
9820                 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);
9821 //              R_Mesh_ResetTextureState();
9822                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
9823                 GL_DepthMask(false);
9824                 GL_DepthRange(0, 1);
9825                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9826                 GL_DepthTest(true);
9827                 GL_CullFace(GL_NONE);
9828                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9829                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
9830                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
9831         }
9832 }
9833
9834 static void R_DrawModelDecals(void)
9835 {
9836         int i, numdecals;
9837
9838         // fade faster when there are too many decals
9839         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9840         for (i = 0;i < r_refdef.scene.numentities;i++)
9841                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9842
9843         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9844         for (i = 0;i < r_refdef.scene.numentities;i++)
9845                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9846                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9847
9848         R_DecalSystem_ApplySplatEntitiesQueue();
9849
9850         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9851         for (i = 0;i < r_refdef.scene.numentities;i++)
9852                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9853
9854         r_refdef.stats[r_stat_totaldecals] += numdecals;
9855
9856         if (r_showsurfaces.integer)
9857                 return;
9858
9859         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9860
9861         for (i = 0;i < r_refdef.scene.numentities;i++)
9862         {
9863                 if (!r_refdef.viewcache.entityvisible[i])
9864                         continue;
9865                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9866                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9867         }
9868 }
9869
9870 extern cvar_t mod_collision_bih;
9871 static void R_DrawDebugModel(void)
9872 {
9873         entity_render_t *ent = rsurface.entity;
9874         int i, j, flagsmask;
9875         const msurface_t *surface;
9876         dp_model_t *model = ent->model;
9877
9878         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
9879                 return;
9880
9881         if (r_showoverdraw.value > 0)
9882         {
9883                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
9884                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9885                 R_SetupShader_Generic_NoTexture(false, false);
9886                 GL_DepthTest(false);
9887                 GL_DepthMask(false);
9888                 GL_DepthRange(0, 1);
9889                 GL_BlendFunc(GL_ONE, GL_ONE);
9890                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9891                 {
9892                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9893                                 continue;
9894                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9895                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9896                         {
9897                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9898                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9899                                 if (!rsurface.texture->currentlayers->depthmask)
9900                                         GL_Color(c, 0, 0, 1.0f);
9901                                 else if (ent == r_refdef.scene.worldentity)
9902                                         GL_Color(c, c, c, 1.0f);
9903                                 else
9904                                         GL_Color(0, c, 0, 1.0f);
9905                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9906                                 RSurf_DrawBatch();
9907                         }
9908                 }
9909                 rsurface.texture = NULL;
9910         }
9911
9912         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9913
9914 //      R_Mesh_ResetTextureState();
9915         R_SetupShader_Generic_NoTexture(false, false);
9916         GL_DepthRange(0, 1);
9917         GL_DepthTest(!r_showdisabledepthtest.integer);
9918         GL_DepthMask(false);
9919         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9920
9921         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
9922         {
9923                 int triangleindex;
9924                 int bihleafindex;
9925                 qboolean cullbox = false;
9926                 const q3mbrush_t *brush;
9927                 const bih_t *bih = &model->collision_bih;
9928                 const bih_leaf_t *bihleaf;
9929                 float vertex3f[3][3];
9930                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9931                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
9932                 {
9933                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
9934                                 continue;
9935                         switch (bihleaf->type)
9936                         {
9937                         case BIH_BRUSH:
9938                                 brush = model->brush.data_brushes + bihleaf->itemindex;
9939                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
9940                                 {
9941                                         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);
9942                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
9943                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
9944                                 }
9945                                 break;
9946                         case BIH_COLLISIONTRIANGLE:
9947                                 triangleindex = bihleaf->itemindex;
9948                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
9949                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
9950                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
9951                                 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);
9952                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9953                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9954                                 break;
9955                         case BIH_RENDERTRIANGLE:
9956                                 triangleindex = bihleaf->itemindex;
9957                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
9958                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
9959                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
9960                                 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);
9961                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9962                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9963                                 break;
9964                         }
9965                 }
9966         }
9967
9968         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9969
9970 #ifndef USE_GLES2
9971         if (r_showtris.value > 0 && qglPolygonMode)
9972         {
9973                 if (r_showdisabledepthtest.integer)
9974                 {
9975                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9976                         GL_DepthMask(false);
9977                 }
9978                 else
9979                 {
9980                         GL_BlendFunc(GL_ONE, GL_ZERO);
9981                         GL_DepthMask(true);
9982                 }
9983                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
9984                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9985                 {
9986                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9987                                 continue;
9988                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9989                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9990                         {
9991                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9992                                 if (!rsurface.texture->currentlayers->depthmask)
9993                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9994                                 else if (ent == r_refdef.scene.worldentity)
9995                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9996                                 else
9997                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9998                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9999                                 RSurf_DrawBatch();
10000                         }
10001                 }
10002                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
10003                 rsurface.texture = NULL;
10004         }
10005
10006 # if 0
10007         // FIXME!  implement r_shownormals with just triangles
10008         if (r_shownormals.value != 0 && qglBegin)
10009         {
10010                 int l, k;
10011                 vec3_t v;
10012                 if (r_showdisabledepthtest.integer)
10013                 {
10014                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10015                         GL_DepthMask(false);
10016                 }
10017                 else
10018                 {
10019                         GL_BlendFunc(GL_ONE, GL_ZERO);
10020                         GL_DepthMask(true);
10021                 }
10022                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10023                 {
10024                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10025                                 continue;
10026                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10027                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10028                         {
10029                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10030                                 qglBegin(GL_LINES);
10031                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
10032                                 {
10033                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10034                                         {
10035                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10036                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10037                                                 qglVertex3f(v[0], v[1], v[2]);
10038                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10039                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10040                                                 qglVertex3f(v[0], v[1], v[2]);
10041                                         }
10042                                 }
10043                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10044                                 {
10045                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10046                                         {
10047                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10048                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10049                                                 qglVertex3f(v[0], v[1], v[2]);
10050                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10051                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10052                                                 qglVertex3f(v[0], v[1], v[2]);
10053                                         }
10054                                 }
10055                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
10056                                 {
10057                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10058                                         {
10059                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10060                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10061                                                 qglVertex3f(v[0], v[1], v[2]);
10062                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10063                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10064                                                 qglVertex3f(v[0], v[1], v[2]);
10065                                         }
10066                                 }
10067                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
10068                                 {
10069                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10070                                         {
10071                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10072                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10073                                                 qglVertex3f(v[0], v[1], v[2]);
10074                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10075                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10076                                                 qglVertex3f(v[0], v[1], v[2]);
10077                                         }
10078                                 }
10079                                 qglEnd();
10080                                 CHECKGLERROR
10081                         }
10082                 }
10083                 rsurface.texture = NULL;
10084         }
10085 # endif
10086 #endif
10087 }
10088
10089 int r_maxsurfacelist = 0;
10090 const msurface_t **r_surfacelist = NULL;
10091 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10092 {
10093         int i, j, endj, flagsmask;
10094         dp_model_t *model = ent->model;
10095         msurface_t *surfaces;
10096         unsigned char *update;
10097         int numsurfacelist = 0;
10098         if (model == NULL)
10099                 return;
10100
10101         if (r_maxsurfacelist < model->num_surfaces)
10102         {
10103                 r_maxsurfacelist = model->num_surfaces;
10104                 if (r_surfacelist)
10105                         Mem_Free((msurface_t **)r_surfacelist);
10106                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10107         }
10108
10109         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10110                 RSurf_ActiveModelEntity(ent, false, false, false);
10111         else if (prepass)
10112                 RSurf_ActiveModelEntity(ent, true, true, true);
10113         else if (depthonly)
10114                 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
10115         else
10116                 RSurf_ActiveModelEntity(ent, true, true, false);
10117
10118         surfaces = model->data_surfaces;
10119         update = model->brushq1.lightmapupdateflags;
10120
10121         // update light styles
10122         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
10123         {
10124                 model_brush_lightstyleinfo_t *style;
10125                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10126                 {
10127                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10128                         {
10129                                 int *list = style->surfacelist;
10130                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10131                                 for (j = 0;j < style->numsurfaces;j++)
10132                                         update[list[j]] = true;
10133                         }
10134                 }
10135         }
10136
10137         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10138
10139         if (debug)
10140         {
10141                 R_DrawDebugModel();
10142                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10143                 return;
10144         }
10145
10146         rsurface.lightmaptexture = NULL;
10147         rsurface.deluxemaptexture = NULL;
10148         rsurface.uselightmaptexture = false;
10149         rsurface.texture = NULL;
10150         rsurface.rtlight = NULL;
10151         numsurfacelist = 0;
10152         // add visible surfaces to draw list
10153         if (ent == r_refdef.scene.worldentity)
10154         {
10155                 // for the world entity, check surfacevisible
10156                 for (i = 0;i < model->nummodelsurfaces;i++)
10157                 {
10158                         j = model->sortedmodelsurfaces[i];
10159                         if (r_refdef.viewcache.world_surfacevisible[j])
10160                                 r_surfacelist[numsurfacelist++] = surfaces + j;
10161                 }
10162         }
10163         else
10164         {
10165                 // add all surfaces
10166                 for (i = 0; i < model->nummodelsurfaces; i++)
10167                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10168         }
10169         // don't do anything if there were no surfaces
10170         if (!numsurfacelist)
10171         {
10172                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10173                 return;
10174         }
10175         // update lightmaps if needed
10176         if (update)
10177         {
10178                 int updated = 0;
10179                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10180                 {
10181                         if (update[j])
10182                         {
10183                                 updated++;
10184                                 R_BuildLightMap(ent, surfaces + j);
10185                         }
10186                 }
10187         }
10188
10189         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10190
10191         // add to stats if desired
10192         if (r_speeds.integer && !skysurfaces && !depthonly)
10193         {
10194                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
10195                 for (j = 0;j < numsurfacelist;j++)
10196                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
10197         }
10198
10199         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10200 }
10201
10202 void R_DebugLine(vec3_t start, vec3_t end)
10203 {
10204         dp_model_t *mod = CL_Mesh_UI();
10205         msurface_t *surf;
10206         int e0, e1, e2, e3;
10207         float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
10208         float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
10209         float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
10210         vec4_t w[2], s[2];
10211
10212         // transform to screen coords first
10213         Vector4Set(w[0], start[0], start[1], start[2], 1);
10214         Vector4Set(w[1], end[0], end[1], end[2], 1);
10215         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
10216         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
10217         x1 = s[0][0] * vid_conwidth.value / vid.width;
10218         y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
10219         x2 = s[1][0] * vid_conwidth.value / vid.width;
10220         y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
10221         //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
10222
10223         // add the line to the UI mesh for drawing later
10224
10225         // width is measured in real pixels
10226         if (fabs(x2 - x1) > fabs(y2 - y1))
10227         {
10228                 offsetx = 0;
10229                 offsety = 0.5f * width * vid_conheight.value / vid.height;
10230         }
10231         else
10232         {
10233                 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
10234                 offsety = 0;
10235         }
10236         surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_VERTEXCOLOR), true);
10237         e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10238         e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10239         e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10240         e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10241         Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
10242         Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
10243
10244 }
10245
10246
10247 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10248 {
10249         int q;
10250         static texture_t texture;
10251         static msurface_t surface;
10252         const msurface_t *surfacelist = &surface;
10253
10254         // fake enough texture and surface state to render this geometry
10255
10256         texture.update_lastrenderframe = -1; // regenerate this texture
10257         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10258         texture.basealpha = 1.0f;
10259         texture.currentskinframe = skinframe;
10260         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10261         texture.offsetmapping = OFFSETMAPPING_OFF;
10262         texture.offsetscale = 1;
10263         texture.specularscalemod = 1;
10264         texture.specularpowermod = 1;
10265         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
10266         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
10267         // JUST GREP FOR "specularscalemod = 1".
10268
10269         for (q = 0; q < 3; q++)
10270         {
10271                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
10272                 texture.render_modellight_lightdir[q] = q == 2;
10273                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10274                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
10275                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
10276                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10277                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
10278                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
10279                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
10280                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
10281         }
10282         texture.currentalpha = 1.0f;
10283
10284         surface.texture = &texture;
10285         surface.num_triangles = numtriangles;
10286         surface.num_firsttriangle = firsttriangle;
10287         surface.num_vertices = numvertices;
10288         surface.num_firstvertex = firstvertex;
10289
10290         // now render it
10291         rsurface.texture = R_GetCurrentTexture(surface.texture);
10292         rsurface.lightmaptexture = NULL;
10293         rsurface.deluxemaptexture = NULL;
10294         rsurface.uselightmaptexture = false;
10295         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10296 }
10297
10298 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)
10299 {
10300         static msurface_t surface;
10301         const msurface_t *surfacelist = &surface;
10302
10303         // fake enough texture and surface state to render this geometry
10304         surface.texture = texture;
10305         surface.num_triangles = numtriangles;
10306         surface.num_firsttriangle = firsttriangle;
10307         surface.num_vertices = numvertices;
10308         surface.num_firstvertex = firstvertex;
10309
10310         // now render it
10311         rsurface.texture = R_GetCurrentTexture(surface.texture);
10312         rsurface.lightmaptexture = NULL;
10313         rsurface.deluxemaptexture = NULL;
10314         rsurface.uselightmaptexture = false;
10315         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10316 }