]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Assume that GL_ARB_texture_compression is supported.
[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 int r_textureframe = 0; ///< used only by R_GetCurrentTexture, incremented per view and per UI render
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                 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1335 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1336                 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1337 #endif
1338                 // clear the uniform block bindings
1339                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1340                 // bind the uniform blocks in use
1341                 ubibind = 0;
1342 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1343                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1344 #endif
1345                 // we're done compiling and setting up the shader, at least until it is used
1346                 CHECKGLERROR
1347                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1348         }
1349         else
1350                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1351
1352         // free the strings
1353         if (sourcestring)
1354                 Mem_Free(sourcestring);
1355 }
1356
1357 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1358 {
1359         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1360         if (r_glsl_permutation != perm)
1361         {
1362                 r_glsl_permutation = perm;
1363                 if (!r_glsl_permutation->program)
1364                 {
1365                         if (!r_glsl_permutation->compiled)
1366                         {
1367                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1368                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1369                         }
1370                         if (!r_glsl_permutation->program)
1371                         {
1372                                 // remove features until we find a valid permutation
1373                                 int i;
1374                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1375                                 {
1376                                         // reduce i more quickly whenever it would not remove any bits
1377                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1378                                         if (!(permutation & j))
1379                                                 continue;
1380                                         permutation -= j;
1381                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1382                                         if (!r_glsl_permutation->compiled)
1383                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1384                                         if (r_glsl_permutation->program)
1385                                                 break;
1386                                 }
1387                                 if (i >= SHADERPERMUTATION_COUNT)
1388                                 {
1389                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1390                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1391                                         qglUseProgram(0);CHECKGLERROR
1392                                         return; // no bit left to clear, entire mode is broken
1393                                 }
1394                         }
1395                 }
1396                 CHECKGLERROR
1397                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1398         }
1399         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1400         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1401         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1402         CHECKGLERROR
1403 }
1404
1405 void R_GLSL_Restart_f(void)
1406 {
1407         unsigned int i, limit;
1408         switch(vid.renderpath)
1409         {
1410         case RENDERPATH_GL32:
1411         case RENDERPATH_GLES2:
1412                 {
1413                         r_glsl_permutation_t *p;
1414                         r_glsl_permutation = NULL;
1415                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1416                         for (i = 0;i < limit;i++)
1417                         {
1418                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1419                                 {
1420                                         GL_Backend_FreeProgram(p->program);
1421                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1422                                 }
1423                         }
1424                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1425                 }
1426                 break;
1427         }
1428 }
1429
1430 static void R_GLSL_DumpShader_f(void)
1431 {
1432         int i, language, mode, dupe;
1433         char *text;
1434         shadermodeinfo_t *modeinfo;
1435         qfile_t *file;
1436
1437         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1438         {
1439                 modeinfo = shadermodeinfo[language];
1440                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1441                 {
1442                         // don't dump the same file multiple times (most or all shaders come from the same file)
1443                         for (dupe = mode - 1;dupe >= 0;dupe--)
1444                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1445                                         break;
1446                         if (dupe >= 0)
1447                                 continue;
1448                         text = modeinfo[mode].builtinstring;
1449                         if (!text)
1450                                 continue;
1451                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1452                         if (file)
1453                         {
1454                                 FS_Print(file, "/* The engine may define the following macros:\n");
1455                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1456                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1457                                         FS_Print(file, modeinfo[i].pretext);
1458                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1459                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1460                                 FS_Print(file, "*/\n");
1461                                 FS_Print(file, text);
1462                                 FS_Close(file);
1463                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1464                         }
1465                         else
1466                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1467                 }
1468         }
1469 }
1470
1471 void R_SetupShader_Generic(rtexture_t *t, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1472 {
1473         dpuint64 permutation = 0;
1474         if (r_trippy.integer && !notrippy)
1475                 permutation |= SHADERPERMUTATION_TRIPPY;
1476         permutation |= SHADERPERMUTATION_VIEWTINT;
1477         if (t)
1478                 permutation |= SHADERPERMUTATION_DIFFUSE;
1479         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1480                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1481         if (suppresstexalpha)
1482                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1483         if (vid.allowalphatocoverage)
1484                 GL_AlphaToCoverage(false);
1485         switch (vid.renderpath)
1486         {
1487         case RENDERPATH_GL32:
1488         case RENDERPATH_GLES2:
1489                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1490                 if (r_glsl_permutation->tex_Texture_First >= 0)
1491                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First, t);
1492                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1493                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1494                 break;
1495         }
1496 }
1497
1498 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1499 {
1500         R_SetupShader_Generic(NULL, usegamma, notrippy, false);
1501 }
1502
1503 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1504 {
1505         dpuint64 permutation = 0;
1506         if (r_trippy.integer && !notrippy)
1507                 permutation |= SHADERPERMUTATION_TRIPPY;
1508         if (depthrgb)
1509                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1510         if (skeletal)
1511                 permutation |= SHADERPERMUTATION_SKELETAL;
1512
1513         if (vid.allowalphatocoverage)
1514                 GL_AlphaToCoverage(false);
1515         switch (vid.renderpath)
1516         {
1517         case RENDERPATH_GL32:
1518         case RENDERPATH_GLES2:
1519                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1520 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1521                 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);
1522 #endif
1523                 break;
1524         }
1525 }
1526
1527 #define BLENDFUNC_ALLOWS_COLORMOD      1
1528 #define BLENDFUNC_ALLOWS_FOG           2
1529 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
1530 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1531 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1532 static int R_BlendFuncFlags(int src, int dst)
1533 {
1534         int r = 0;
1535
1536         // a blendfunc allows colormod if:
1537         // a) it can never keep the destination pixel invariant, or
1538         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1539         // this is to prevent unintended side effects from colormod
1540
1541         // a blendfunc allows fog if:
1542         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
1543         // this is to prevent unintended side effects from fog
1544
1545         // these checks are the output of fogeval.pl
1546
1547         r |= BLENDFUNC_ALLOWS_COLORMOD;
1548         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1549         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1550         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1551         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1552         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1553         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1554         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1555         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1556         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
1557         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
1558         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1559         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1560         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1561         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1562         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1563         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1564         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1565         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1566         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1567         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
1568         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1569
1570         return r;
1571 }
1572
1573 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)
1574 {
1575         // select a permutation of the lighting shader appropriate to this
1576         // combination of texture, entity, light source, and fogging, only use the
1577         // minimum features necessary to avoid wasting rendering time in the
1578         // fragment shader on features that are not being used
1579         dpuint64 permutation = 0;
1580         unsigned int mode = 0;
1581         int blendfuncflags;
1582         texture_t *t = rsurface.texture;
1583         float m16f[16];
1584         matrix4x4_t tempmatrix;
1585         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
1586         if (r_trippy.integer && !notrippy)
1587                 permutation |= SHADERPERMUTATION_TRIPPY;
1588         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
1589                 permutation |= SHADERPERMUTATION_ALPHAKILL;
1590         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
1591                 permutation |= SHADERPERMUTATION_OCCLUDE;
1592         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
1593                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
1594         if (rsurfacepass == RSURFPASS_BACKGROUND)
1595         {
1596                 // distorted background
1597                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1598                 {
1599                         mode = SHADERMODE_WATER;
1600                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1601                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1602                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
1603                         {
1604                                 // this is the right thing to do for wateralpha
1605                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1606                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1607                         }
1608                         else
1609                         {
1610                                 // this is the right thing to do for entity alpha
1611                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1612                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1613                         }
1614                 }
1615                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
1616                 {
1617                         mode = SHADERMODE_REFRACTION;
1618                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1619                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1620                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1621                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1622                 }
1623                 else
1624                 {
1625                         mode = SHADERMODE_GENERIC;
1626                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
1627                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1628                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1629                 }
1630                 if (vid.allowalphatocoverage)
1631                         GL_AlphaToCoverage(false);
1632         }
1633         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
1634         {
1635                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1636                 {
1637                         switch(t->offsetmapping)
1638                         {
1639                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1640                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1641                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1642                         case OFFSETMAPPING_OFF: break;
1643                         }
1644                 }
1645                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1646                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1647                 // normalmap (deferred prepass), may use alpha test on diffuse
1648                 mode = SHADERMODE_DEFERREDGEOMETRY;
1649                 GL_BlendFunc(GL_ONE, GL_ZERO);
1650                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1651                 if (vid.allowalphatocoverage)
1652                         GL_AlphaToCoverage(false);
1653         }
1654         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1655         {
1656                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1657                 {
1658                         switch(t->offsetmapping)
1659                         {
1660                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1661                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1662                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1663                         case OFFSETMAPPING_OFF: break;
1664                         }
1665                 }
1666                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1667                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1668                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1669                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1670                 // light source
1671                 mode = SHADERMODE_LIGHTSOURCE;
1672                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1673                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1674                 if (VectorLength2(rtlightdiffuse) > 0)
1675                         permutation |= SHADERPERMUTATION_DIFFUSE;
1676                 if (VectorLength2(rtlightspecular) > 0)
1677                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1678                 if (r_refdef.fogenabled)
1679                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1680                 if (t->colormapping)
1681                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1682                 if (r_shadow_usingshadowmap2d)
1683                 {
1684                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1685                         if(r_shadow_shadowmapvsdct)
1686                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
1687
1688                         if (r_shadow_shadowmap2ddepthbuffer)
1689                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1690                 }
1691                 if (t->reflectmasktexture)
1692                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1693                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1694                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
1695                 if (vid.allowalphatocoverage)
1696                         GL_AlphaToCoverage(false);
1697         }
1698         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1699         {
1700                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1701                 {
1702                         switch(t->offsetmapping)
1703                         {
1704                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1705                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1706                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1707                         case OFFSETMAPPING_OFF: break;
1708                         }
1709                 }
1710                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1711                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1712                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1713                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1714                 // directional model lighting
1715                 mode = SHADERMODE_LIGHTDIRECTION;
1716                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1717                         permutation |= SHADERPERMUTATION_GLOW;
1718                 if (VectorLength2(t->render_modellight_diffuse))
1719                         permutation |= SHADERPERMUTATION_DIFFUSE;
1720                 if (VectorLength2(t->render_modellight_specular) > 0)
1721                         permutation |= SHADERPERMUTATION_SPECULAR;
1722                 if (r_refdef.fogenabled)
1723                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1724                 if (t->colormapping)
1725                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1726                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1727                 {
1728                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1729                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1730
1731                         if (r_shadow_shadowmap2ddepthbuffer)
1732                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1733                 }
1734                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1735                         permutation |= SHADERPERMUTATION_REFLECTION;
1736                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1737                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1738                 if (t->reflectmasktexture)
1739                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1740                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1741                 {
1742                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1743                         if (r_shadow_bouncegrid_state.directional)
1744                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1745                 }
1746                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1747                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1748                 // when using alphatocoverage, we don't need alphakill
1749                 if (vid.allowalphatocoverage)
1750                 {
1751                         if (r_transparent_alphatocoverage.integer)
1752                         {
1753                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1754                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1755                         }
1756                         else
1757                                 GL_AlphaToCoverage(false);
1758                 }
1759         }
1760         else
1761         {
1762                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1763                 {
1764                         switch(t->offsetmapping)
1765                         {
1766                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1767                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1768                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1769                         case OFFSETMAPPING_OFF: break;
1770                         }
1771                 }
1772                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1773                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1774                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1775                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1776                 // lightmapped wall
1777                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1778                         permutation |= SHADERPERMUTATION_GLOW;
1779                 if (r_refdef.fogenabled)
1780                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1781                 if (t->colormapping)
1782                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1783                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1784                 {
1785                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1786                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1787
1788                         if (r_shadow_shadowmap2ddepthbuffer)
1789                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1790                 }
1791                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1792                         permutation |= SHADERPERMUTATION_REFLECTION;
1793                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1794                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1795                 if (t->reflectmasktexture)
1796                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1797                 if (FAKELIGHT_ENABLED)
1798                 {
1799                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
1800                         mode = SHADERMODE_FAKELIGHT;
1801                         permutation |= SHADERPERMUTATION_DIFFUSE;
1802                         if (VectorLength2(t->render_lightmap_specular) > 0)
1803                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1804                 }
1805                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1806                 {
1807                         // deluxemapping (light direction texture)
1808                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1809                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1810                         else
1811                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1812                         permutation |= SHADERPERMUTATION_DIFFUSE;
1813                         if (VectorLength2(t->render_lightmap_specular) > 0)
1814                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1815                 }
1816                 else if (r_glsl_deluxemapping.integer >= 2)
1817                 {
1818                         // fake deluxemapping (uniform light direction in tangentspace)
1819                         if (rsurface.uselightmaptexture)
1820                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
1821                         else
1822                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
1823                         permutation |= SHADERPERMUTATION_DIFFUSE;
1824                         if (VectorLength2(t->render_lightmap_specular) > 0)
1825                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1826                 }
1827                 else if (rsurface.uselightmaptexture)
1828                 {
1829                         // ordinary lightmapping (q1bsp, q3bsp)
1830                         mode = SHADERMODE_LIGHTMAP;
1831                 }
1832                 else
1833                 {
1834                         // ordinary vertex coloring (q3bsp)
1835                         mode = SHADERMODE_VERTEXCOLOR;
1836                 }
1837                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1838                 {
1839                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1840                         if (r_shadow_bouncegrid_state.directional)
1841                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1842                 }
1843                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1844                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1845                 // when using alphatocoverage, we don't need alphakill
1846                 if (vid.allowalphatocoverage)
1847                 {
1848                         if (r_transparent_alphatocoverage.integer)
1849                         {
1850                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1851                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1852                         }
1853                         else
1854                                 GL_AlphaToCoverage(false);
1855                 }
1856         }
1857         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
1858                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
1859         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1860                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
1861         switch(vid.renderpath)
1862         {
1863         case RENDERPATH_GL32:
1864         case RENDERPATH_GLES2:
1865                 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);
1866                 R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
1867                 R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
1868                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
1869                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
1870                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
1871                 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
1872                 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
1873                 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
1874                 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
1875                 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
1876                 // this has to be after RSurf_PrepareVerticesForBatch
1877                 if (rsurface.batchskeletaltransform3x4buffer)
1878                         permutation |= SHADERPERMUTATION_SKELETAL;
1879                 R_SetupShader_SetPermutationGLSL(mode, permutation);
1880 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1881                 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);
1882 #endif
1883                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
1884                 if (mode == SHADERMODE_LIGHTSOURCE)
1885                 {
1886                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
1887                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1888                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1889                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
1890                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
1891                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
1892         
1893                         // additive passes are only darkened by fog, not tinted
1894                         if (r_glsl_permutation->loc_FogColor >= 0)
1895                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1896                         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);
1897                 }
1898                 else
1899                 {
1900                         if (mode == SHADERMODE_FLATCOLOR)
1901                         {
1902                                 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]);
1903                         }
1904                         else if (mode == SHADERMODE_LIGHTDIRECTION)
1905                         {
1906                                 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]);
1907                                 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]);
1908                                 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]);
1909                                 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]);
1910                                 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]);
1911                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1912                                 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]);
1913                         }
1914                         else
1915                         {
1916                                 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]);
1917                                 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]);
1918                                 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]);
1919                                 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]);
1920                                 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]);
1921                         }
1922                         // additive passes are only darkened by fog, not tinted
1923                         if (r_glsl_permutation->loc_FogColor >= 0)
1924                         {
1925                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
1926                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1927                                 else
1928                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1929                         }
1930                         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);
1931                         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]);
1932                         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]);
1933                         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);
1934                         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);
1935                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
1936                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
1937                         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);
1938                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
1939                 }
1940                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
1941                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
1942                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
1943                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
1944                 {
1945                         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]);
1946                         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]);
1947                 }
1948                 else
1949                 {
1950                         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]);
1951                         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]);
1952                 }
1953
1954                 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]);
1955                 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));
1956                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
1957                 if (r_glsl_permutation->loc_Color_Pants >= 0)
1958                 {
1959                         if (t->pantstexture)
1960                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
1961                         else
1962                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1963                 }
1964                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1965                 {
1966                         if (t->shirttexture)
1967                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
1968                         else
1969                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1970                 }
1971                 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]);
1972                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
1973                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
1974                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
1975                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
1976                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
1977                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1978                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1979                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
1980                         );
1981                 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);
1982                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
1983                 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]);
1984                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
1985                 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);}
1986                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
1987
1988                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
1989                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
1990                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
1991                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
1992                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
1993                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
1994                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
1995                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
1996                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
1997                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
1998                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
1999                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2000                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2001                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2002                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2003                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2004                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2005                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2006                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2007                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2008                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2009                 {
2010                         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);
2011                         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);
2012                         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);
2013                 }
2014                 else
2015                 {
2016                         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);
2017                 }
2018                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2019                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2020                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2021                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2022                 {
2023                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2024                         if (rsurface.rtlight)
2025                         {
2026                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2027                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2028                         }
2029                 }
2030                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2031                 CHECKGLERROR
2032                 break;
2033         }
2034 }
2035
2036 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2037 {
2038         // select a permutation of the lighting shader appropriate to this
2039         // combination of texture, entity, light source, and fogging, only use the
2040         // minimum features necessary to avoid wasting rendering time in the
2041         // fragment shader on features that are not being used
2042         dpuint64 permutation = 0;
2043         unsigned int mode = 0;
2044         const float *lightcolorbase = rtlight->currentcolor;
2045         float ambientscale = rtlight->ambientscale;
2046         float diffusescale = rtlight->diffusescale;
2047         float specularscale = rtlight->specularscale;
2048         // this is the location of the light in view space
2049         vec3_t viewlightorigin;
2050         // this transforms from view space (camera) to light space (cubemap)
2051         matrix4x4_t viewtolight;
2052         matrix4x4_t lighttoview;
2053         float viewtolight16f[16];
2054         // light source
2055         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2056         if (rtlight->currentcubemap != r_texture_whitecube)
2057                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2058         if (diffusescale > 0)
2059                 permutation |= SHADERPERMUTATION_DIFFUSE;
2060         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2061                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2062         if (r_shadow_usingshadowmap2d)
2063         {
2064                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2065                 if (r_shadow_shadowmapvsdct)
2066                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2067
2068                 if (r_shadow_shadowmap2ddepthbuffer)
2069                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2070         }
2071         if (vid.allowalphatocoverage)
2072                 GL_AlphaToCoverage(false);
2073         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2074         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2075         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2076         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2077         switch(vid.renderpath)
2078         {
2079         case RENDERPATH_GL32:
2080         case RENDERPATH_GLES2:
2081                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2082                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2083                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2084                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
2085                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
2086                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
2087                 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]);
2088                 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]);
2089                 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);
2090                 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]);
2091                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2092
2093                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2094                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2095                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2096                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
2097                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2098                 break;
2099         }
2100 }
2101
2102 #define SKINFRAME_HASH 1024
2103
2104 typedef struct
2105 {
2106         unsigned int loadsequence; // incremented each level change
2107         memexpandablearray_t array;
2108         skinframe_t *hash[SKINFRAME_HASH];
2109 }
2110 r_skinframe_t;
2111 r_skinframe_t r_skinframe;
2112
2113 void R_SkinFrame_PrepareForPurge(void)
2114 {
2115         r_skinframe.loadsequence++;
2116         // wrap it without hitting zero
2117         if (r_skinframe.loadsequence >= 200)
2118                 r_skinframe.loadsequence = 1;
2119 }
2120
2121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2122 {
2123         if (!skinframe)
2124                 return;
2125         // mark the skinframe as used for the purging code
2126         skinframe->loadsequence = r_skinframe.loadsequence;
2127 }
2128
2129 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
2130 {
2131         if (s == NULL)
2132                 return;
2133         if (s->merged == s->base)
2134                 s->merged = NULL;
2135         R_PurgeTexture(s->stain); s->stain = NULL;
2136         R_PurgeTexture(s->merged); s->merged = NULL;
2137         R_PurgeTexture(s->base); s->base = NULL;
2138         R_PurgeTexture(s->pants); s->pants = NULL;
2139         R_PurgeTexture(s->shirt); s->shirt = NULL;
2140         R_PurgeTexture(s->nmap); s->nmap = NULL;
2141         R_PurgeTexture(s->gloss); s->gloss = NULL;
2142         R_PurgeTexture(s->glow); s->glow = NULL;
2143         R_PurgeTexture(s->fog); s->fog = NULL;
2144         R_PurgeTexture(s->reflect); s->reflect = NULL;
2145         s->loadsequence = 0;
2146 }
2147
2148 void R_SkinFrame_Purge(void)
2149 {
2150         int i;
2151         skinframe_t *s;
2152         for (i = 0;i < SKINFRAME_HASH;i++)
2153         {
2154                 for (s = r_skinframe.hash[i];s;s = s->next)
2155                 {
2156                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2157                                 R_SkinFrame_PurgeSkinFrame(s);
2158                 }
2159         }
2160 }
2161
2162 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2163         skinframe_t *item;
2164         char basename[MAX_QPATH];
2165
2166         Image_StripImageExtension(name, basename, sizeof(basename));
2167
2168         if( last == NULL ) {
2169                 int hashindex;
2170                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2171                 item = r_skinframe.hash[hashindex];
2172         } else {
2173                 item = last->next;
2174         }
2175
2176         // linearly search through the hash bucket
2177         for( ; item ; item = item->next ) {
2178                 if( !strcmp( item->basename, basename ) ) {
2179                         return item;
2180                 }
2181         }
2182         return NULL;
2183 }
2184
2185 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2186 {
2187         skinframe_t *item;
2188         int compareflags = textureflags & TEXF_IMPORTANTBITS;
2189         int hashindex;
2190         char basename[MAX_QPATH];
2191
2192         Image_StripImageExtension(name, basename, sizeof(basename));
2193
2194         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2195         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2196                 if (!strcmp(item->basename, basename) &&
2197                         item->textureflags == compareflags &&
2198                         item->comparewidth == comparewidth &&
2199                         item->compareheight == compareheight &&
2200                         item->comparecrc == comparecrc)
2201                         break;
2202
2203         if (!item)
2204         {
2205                 if (!add)
2206                         return NULL;
2207                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2208                 memset(item, 0, sizeof(*item));
2209                 strlcpy(item->basename, basename, sizeof(item->basename));
2210                 item->textureflags = compareflags;
2211                 item->comparewidth = comparewidth;
2212                 item->compareheight = compareheight;
2213                 item->comparecrc = comparecrc;
2214                 item->next = r_skinframe.hash[hashindex];
2215                 r_skinframe.hash[hashindex] = item;
2216         }
2217         else if (textureflags & TEXF_FORCE_RELOAD)
2218                 R_SkinFrame_PurgeSkinFrame(item);
2219
2220         R_SkinFrame_MarkUsed(item);
2221         return item;
2222 }
2223
2224 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2225         { \
2226                 unsigned long long avgcolor[5], wsum; \
2227                 int pix, comp, w; \
2228                 avgcolor[0] = 0; \
2229                 avgcolor[1] = 0; \
2230                 avgcolor[2] = 0; \
2231                 avgcolor[3] = 0; \
2232                 avgcolor[4] = 0; \
2233                 wsum = 0; \
2234                 for(pix = 0; pix < cnt; ++pix) \
2235                 { \
2236                         w = 0; \
2237                         for(comp = 0; comp < 3; ++comp) \
2238                                 w += getpixel; \
2239                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2240                         { \
2241                                 ++wsum; \
2242                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2243                                 w = getpixel; \
2244                                 for(comp = 0; comp < 3; ++comp) \
2245                                         avgcolor[comp] += getpixel * w; \
2246                                 avgcolor[3] += w; \
2247                         } \
2248                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2249                         avgcolor[4] += getpixel; \
2250                 } \
2251                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2252                         avgcolor[3] = 1; \
2253                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2254                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2255                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2256                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2257         }
2258
2259 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2260 {
2261         skinframe_t *skinframe;
2262
2263         if (cls.state == ca_dedicated)
2264                 return NULL;
2265
2266         // return an existing skinframe if already loaded
2267         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2268         if (skinframe && skinframe->base)
2269                 return skinframe;
2270
2271         // if the skinframe doesn't exist this will create it
2272         return R_SkinFrame_LoadExternal_SkinFrame(skinframe, name, textureflags, complain, fallbacknotexture);
2273 }
2274
2275 extern cvar_t gl_picmip;
2276 skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2277 {
2278         int j;
2279         unsigned char *pixels;
2280         unsigned char *bumppixels;
2281         unsigned char *basepixels = NULL;
2282         int basepixels_width = 0;
2283         int basepixels_height = 0;
2284         rtexture_t *ddsbase = NULL;
2285         qboolean ddshasalpha = false;
2286         float ddsavgcolor[4];
2287         char basename[MAX_QPATH];
2288         int miplevel = R_PicmipForFlags(textureflags);
2289         int savemiplevel = miplevel;
2290         int mymiplevel;
2291         char vabuf[1024];
2292
2293         if (cls.state == ca_dedicated)
2294                 return NULL;
2295
2296         Image_StripImageExtension(name, basename, sizeof(basename));
2297
2298         // check for DDS texture file first
2299         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
2300         {
2301                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
2302                 if (basepixels == NULL && fallbacknotexture)
2303                         basepixels = Image_GenerateNoTexture();
2304                 if (basepixels == NULL)
2305                         return NULL;
2306         }
2307
2308         // FIXME handle miplevel
2309
2310         if (developer_loading.integer)
2311                 Con_Printf("loading skin \"%s\"\n", name);
2312
2313         // we've got some pixels to store, so really allocate this new texture now
2314         if (!skinframe)
2315                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2316         textureflags &= ~TEXF_FORCE_RELOAD;
2317         skinframe->stain = NULL;
2318         skinframe->merged = NULL;
2319         skinframe->base = NULL;
2320         skinframe->pants = NULL;
2321         skinframe->shirt = NULL;
2322         skinframe->nmap = NULL;
2323         skinframe->gloss = NULL;
2324         skinframe->glow = NULL;
2325         skinframe->fog = NULL;
2326         skinframe->reflect = NULL;
2327         skinframe->hasalpha = false;
2328         // we could store the q2animname here too
2329
2330         if (ddsbase)
2331         {
2332                 skinframe->base = ddsbase;
2333                 skinframe->hasalpha = ddshasalpha;
2334                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
2335                 if (r_loadfog && skinframe->hasalpha)
2336                         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);
2337                 //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]);
2338         }
2339         else
2340         {
2341                 basepixels_width = image_width;
2342                 basepixels_height = image_height;
2343                 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);
2344                 if (textureflags & TEXF_ALPHA)
2345                 {
2346                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2347                         {
2348                                 if (basepixels[j] < 255)
2349                                 {
2350                                         skinframe->hasalpha = true;
2351                                         break;
2352                                 }
2353                         }
2354                         if (r_loadfog && skinframe->hasalpha)
2355                         {
2356                                 // has transparent pixels
2357                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2358                                 for (j = 0;j < image_width * image_height * 4;j += 4)
2359                                 {
2360                                         pixels[j+0] = 255;
2361                                         pixels[j+1] = 255;
2362                                         pixels[j+2] = 255;
2363                                         pixels[j+3] = basepixels[j+3];
2364                                 }
2365                                 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);
2366                                 Mem_Free(pixels);
2367                         }
2368                 }
2369                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2370 #ifndef USE_GLES2
2371                 //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]);
2372                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
2373                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
2374                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
2375                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2376 #endif
2377         }
2378
2379         if (r_loaddds)
2380         {
2381                 mymiplevel = savemiplevel;
2382                 if (r_loadnormalmap)
2383                         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);
2384                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2385                 if (r_loadgloss)
2386                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2387                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2388                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2389                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2390         }
2391
2392         // _norm is the name used by tenebrae and has been adopted as standard
2393         if (r_loadnormalmap && skinframe->nmap == NULL)
2394         {
2395                 mymiplevel = savemiplevel;
2396                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2397                 {
2398                         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);
2399                         Mem_Free(pixels);
2400                         pixels = NULL;
2401                 }
2402                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2403                 {
2404                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2405                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2406                         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);
2407                         Mem_Free(pixels);
2408                         Mem_Free(bumppixels);
2409                 }
2410                 else if (r_shadow_bumpscale_basetexture.value > 0)
2411                 {
2412                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2413                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2414                         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);
2415                         Mem_Free(pixels);
2416                 }
2417 #ifndef USE_GLES2
2418                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
2419                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2420 #endif
2421         }
2422
2423         // _luma is supported only for tenebrae compatibility
2424         // _glow is the preferred name
2425         mymiplevel = savemiplevel;
2426         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))))
2427         {
2428                 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);
2429 #ifndef USE_GLES2
2430                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
2431                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2432 #endif
2433                 Mem_Free(pixels);pixels = NULL;
2434         }
2435
2436         mymiplevel = savemiplevel;
2437         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
2438         {
2439                 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);
2440 #ifndef USE_GLES2
2441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
2442                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2443 #endif
2444                 Mem_Free(pixels);
2445                 pixels = NULL;
2446         }
2447
2448         mymiplevel = savemiplevel;
2449         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
2450         {
2451                 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);
2452 #ifndef USE_GLES2
2453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
2454                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2455 #endif
2456                 Mem_Free(pixels);
2457                 pixels = NULL;
2458         }
2459
2460         mymiplevel = savemiplevel;
2461         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
2462         {
2463                 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);
2464 #ifndef USE_GLES2
2465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
2466                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2467 #endif
2468                 Mem_Free(pixels);
2469                 pixels = NULL;
2470         }
2471
2472         mymiplevel = savemiplevel;
2473         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
2474         {
2475                 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);
2476 #ifndef USE_GLES2
2477                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
2478                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2479 #endif
2480                 Mem_Free(pixels);
2481                 pixels = NULL;
2482         }
2483
2484         if (basepixels)
2485                 Mem_Free(basepixels);
2486
2487         return skinframe;
2488 }
2489
2490 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, int comparewidth, int compareheight, int comparecrc, qboolean sRGB)
2491 {
2492         int i;
2493         skinframe_t *skinframe;
2494         char vabuf[1024];
2495
2496         if (cls.state == ca_dedicated)
2497                 return NULL;
2498
2499         // if already loaded just return it, otherwise make a new skinframe
2500         skinframe = R_SkinFrame_Find(name, textureflags, comparewidth, compareheight, comparecrc, true);
2501         if (skinframe->base)
2502                 return skinframe;
2503         textureflags &= ~TEXF_FORCE_RELOAD;
2504
2505         skinframe->stain = NULL;
2506         skinframe->merged = NULL;
2507         skinframe->base = NULL;
2508         skinframe->pants = NULL;
2509         skinframe->shirt = NULL;
2510         skinframe->nmap = NULL;
2511         skinframe->gloss = NULL;
2512         skinframe->glow = NULL;
2513         skinframe->fog = NULL;
2514         skinframe->reflect = NULL;
2515         skinframe->hasalpha = false;
2516
2517         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2518         if (!skindata)
2519                 return NULL;
2520
2521         if (developer_loading.integer)
2522                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2523
2524         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2525         {
2526                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2527                 unsigned char *b = a + width * height * 4;
2528                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2529                 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);
2530                 Mem_Free(a);
2531         }
2532         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
2533         if (textureflags & TEXF_ALPHA)
2534         {
2535                 for (i = 3;i < width * height * 4;i += 4)
2536                 {
2537                         if (skindata[i] < 255)
2538                         {
2539                                 skinframe->hasalpha = true;
2540                                 break;
2541                         }
2542                 }
2543                 if (r_loadfog && skinframe->hasalpha)
2544                 {
2545                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2546                         memcpy(fogpixels, skindata, width * height * 4);
2547                         for (i = 0;i < width * height * 4;i += 4)
2548                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2549                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
2550                         Mem_Free(fogpixels);
2551                 }
2552         }
2553
2554         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2555         //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]);
2556
2557         return skinframe;
2558 }
2559
2560 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2561 {
2562         int i;
2563         int featuresmask;
2564         skinframe_t *skinframe;
2565
2566         if (cls.state == ca_dedicated)
2567                 return NULL;
2568
2569         // if already loaded just return it, otherwise make a new skinframe
2570         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2571         if (skinframe->base)
2572                 return skinframe;
2573         //textureflags &= ~TEXF_FORCE_RELOAD;
2574
2575         skinframe->stain = NULL;
2576         skinframe->merged = NULL;
2577         skinframe->base = NULL;
2578         skinframe->pants = NULL;
2579         skinframe->shirt = NULL;
2580         skinframe->nmap = NULL;
2581         skinframe->gloss = NULL;
2582         skinframe->glow = NULL;
2583         skinframe->fog = NULL;
2584         skinframe->reflect = NULL;
2585         skinframe->hasalpha = false;
2586
2587         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2588         if (!skindata)
2589                 return NULL;
2590
2591         if (developer_loading.integer)
2592                 Con_Printf("loading quake skin \"%s\"\n", name);
2593
2594         // 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)
2595         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
2596         memcpy(skinframe->qpixels, skindata, width*height);
2597         skinframe->qwidth = width;
2598         skinframe->qheight = height;
2599
2600         featuresmask = 0;
2601         for (i = 0;i < width * height;i++)
2602                 featuresmask |= palette_featureflags[skindata[i]];
2603
2604         skinframe->hasalpha = false;
2605         // fence textures
2606         if (name[0] == '{')
2607                 skinframe->hasalpha = true;
2608         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2609         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2610         skinframe->qgeneratemerged = true;
2611         skinframe->qgeneratebase = skinframe->qhascolormapping;
2612         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2613
2614         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2615         //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]);
2616
2617         return skinframe;
2618 }
2619
2620 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2621 {
2622         int width;
2623         int height;
2624         unsigned char *skindata;
2625         char vabuf[1024];
2626
2627         if (!skinframe->qpixels)
2628                 return;
2629
2630         if (!skinframe->qhascolormapping)
2631                 colormapped = false;
2632
2633         if (colormapped)
2634         {
2635                 if (!skinframe->qgeneratebase)
2636                         return;
2637         }
2638         else
2639         {
2640                 if (!skinframe->qgeneratemerged)
2641                         return;
2642         }
2643
2644         width = skinframe->qwidth;
2645         height = skinframe->qheight;
2646         skindata = skinframe->qpixels;
2647
2648         if (skinframe->qgeneratenmap)
2649         {
2650                 unsigned char *a, *b;
2651                 skinframe->qgeneratenmap = false;
2652                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2653                 b = a + width * height * 4;
2654                 // use either a custom palette or the quake palette
2655                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
2656                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2657                 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);
2658                 Mem_Free(a);
2659         }
2660
2661         if (skinframe->qgenerateglow)
2662         {
2663                 skinframe->qgenerateglow = false;
2664                 if (skinframe->hasalpha) // fence textures
2665                         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
2666                 else
2667                         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
2668         }
2669
2670         if (colormapped)
2671         {
2672                 skinframe->qgeneratebase = false;
2673                 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);
2674                 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);
2675                 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);
2676         }
2677         else
2678         {
2679                 skinframe->qgeneratemerged = false;
2680                 if (skinframe->hasalpha) // fence textures
2681                         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);
2682                 else
2683                         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);
2684         }
2685
2686         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2687         {
2688                 Mem_Free(skinframe->qpixels);
2689                 skinframe->qpixels = NULL;
2690         }
2691 }
2692
2693 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)
2694 {
2695         int i;
2696         skinframe_t *skinframe;
2697         char vabuf[1024];
2698
2699         if (cls.state == ca_dedicated)
2700                 return NULL;
2701
2702         // if already loaded just return it, otherwise make a new skinframe
2703         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2704         if (skinframe->base)
2705                 return skinframe;
2706         textureflags &= ~TEXF_FORCE_RELOAD;
2707
2708         skinframe->stain = NULL;
2709         skinframe->merged = NULL;
2710         skinframe->base = NULL;
2711         skinframe->pants = NULL;
2712         skinframe->shirt = NULL;
2713         skinframe->nmap = NULL;
2714         skinframe->gloss = NULL;
2715         skinframe->glow = NULL;
2716         skinframe->fog = NULL;
2717         skinframe->reflect = NULL;
2718         skinframe->hasalpha = false;
2719
2720         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2721         if (!skindata)
2722                 return NULL;
2723
2724         if (developer_loading.integer)
2725                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2726
2727         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
2728         if ((textureflags & TEXF_ALPHA) && alphapalette)
2729         {
2730                 for (i = 0;i < width * height;i++)
2731                 {
2732                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2733                         {
2734                                 skinframe->hasalpha = true;
2735                                 break;
2736                         }
2737                 }
2738                 if (r_loadfog && skinframe->hasalpha)
2739                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
2740         }
2741
2742         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2743         //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]);
2744
2745         return skinframe;
2746 }
2747
2748 skinframe_t *R_SkinFrame_LoadMissing(void)
2749 {
2750         skinframe_t *skinframe;
2751
2752         if (cls.state == ca_dedicated)
2753                 return NULL;
2754
2755         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
2756         skinframe->stain = NULL;
2757         skinframe->merged = NULL;
2758         skinframe->base = NULL;
2759         skinframe->pants = NULL;
2760         skinframe->shirt = NULL;
2761         skinframe->nmap = NULL;
2762         skinframe->gloss = NULL;
2763         skinframe->glow = NULL;
2764         skinframe->fog = NULL;
2765         skinframe->reflect = NULL;
2766         skinframe->hasalpha = false;
2767
2768         skinframe->avgcolor[0] = rand() / RAND_MAX;
2769         skinframe->avgcolor[1] = rand() / RAND_MAX;
2770         skinframe->avgcolor[2] = rand() / RAND_MAX;
2771         skinframe->avgcolor[3] = 1;
2772
2773         return skinframe;
2774 }
2775
2776 skinframe_t *R_SkinFrame_LoadNoTexture(void)
2777 {
2778         int x, y;
2779         static unsigned char pix[16][16][4];
2780
2781         if (cls.state == ca_dedicated)
2782                 return NULL;
2783
2784         // this makes a light grey/dark grey checkerboard texture
2785         if (!pix[0][0][3])
2786         {
2787                 for (y = 0; y < 16; y++)
2788                 {
2789                         for (x = 0; x < 16; x++)
2790                         {
2791                                 if ((y < 8) ^ (x < 8))
2792                                 {
2793                                         pix[y][x][0] = 128;
2794                                         pix[y][x][1] = 128;
2795                                         pix[y][x][2] = 128;
2796                                         pix[y][x][3] = 255;
2797                                 }
2798                                 else
2799                                 {
2800                                         pix[y][x][0] = 64;
2801                                         pix[y][x][1] = 64;
2802                                         pix[y][x][2] = 64;
2803                                         pix[y][x][3] = 255;
2804                                 }
2805                         }
2806                 }
2807         }
2808
2809         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, 0, 0, 0, false);
2810 }
2811
2812 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
2813 {
2814         skinframe_t *skinframe;
2815         if (cls.state == ca_dedicated)
2816                 return NULL;
2817         // if already loaded just return it, otherwise make a new skinframe
2818         skinframe = R_SkinFrame_Find(name, textureflags, width, height, 0, true);
2819         if (skinframe->base)
2820                 return skinframe;
2821         textureflags &= ~TEXF_FORCE_RELOAD;
2822         skinframe->stain = NULL;
2823         skinframe->merged = NULL;
2824         skinframe->base = NULL;
2825         skinframe->pants = NULL;
2826         skinframe->shirt = NULL;
2827         skinframe->nmap = NULL;
2828         skinframe->gloss = NULL;
2829         skinframe->glow = NULL;
2830         skinframe->fog = NULL;
2831         skinframe->reflect = NULL;
2832         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
2833         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2834         if (!tex)
2835                 return NULL;
2836         if (developer_loading.integer)
2837                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2838         skinframe->base = skinframe->merged = tex;
2839         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
2840         return skinframe;
2841 }
2842
2843 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
2844 typedef struct suffixinfo_s
2845 {
2846         const char *suffix;
2847         qboolean flipx, flipy, flipdiagonal;
2848 }
2849 suffixinfo_t;
2850 static suffixinfo_t suffix[3][6] =
2851 {
2852         {
2853                 {"px",   false, false, false},
2854                 {"nx",   false, false, false},
2855                 {"py",   false, false, false},
2856                 {"ny",   false, false, false},
2857                 {"pz",   false, false, false},
2858                 {"nz",   false, false, false}
2859         },
2860         {
2861                 {"posx", false, false, false},
2862                 {"negx", false, false, false},
2863                 {"posy", false, false, false},
2864                 {"negy", false, false, false},
2865                 {"posz", false, false, false},
2866                 {"negz", false, false, false}
2867         },
2868         {
2869                 {"rt",    true, false,  true},
2870                 {"lf",   false,  true,  true},
2871                 {"ft",    true,  true, false},
2872                 {"bk",   false, false, false},
2873                 {"up",    true, false,  true},
2874                 {"dn",    true, false,  true}
2875         }
2876 };
2877
2878 static int componentorder[4] = {0, 1, 2, 3};
2879
2880 static rtexture_t *R_LoadCubemap(const char *basename)
2881 {
2882         int i, j, cubemapsize;
2883         unsigned char *cubemappixels, *image_buffer;
2884         rtexture_t *cubemaptexture;
2885         char name[256];
2886         // must start 0 so the first loadimagepixels has no requested width/height
2887         cubemapsize = 0;
2888         cubemappixels = NULL;
2889         cubemaptexture = NULL;
2890         // keep trying different suffix groups (posx, px, rt) until one loads
2891         for (j = 0;j < 3 && !cubemappixels;j++)
2892         {
2893                 // load the 6 images in the suffix group
2894                 for (i = 0;i < 6;i++)
2895                 {
2896                         // generate an image name based on the base and and suffix
2897                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
2898                         // load it
2899                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
2900                         {
2901                                 // an image loaded, make sure width and height are equal
2902                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
2903                                 {
2904                                         // if this is the first image to load successfully, allocate the cubemap memory
2905                                         if (!cubemappixels && image_width >= 1)
2906                                         {
2907                                                 cubemapsize = image_width;
2908                                                 // note this clears to black, so unavailable sides are black
2909                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
2910                                         }
2911                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
2912                                         if (cubemappixels)
2913                                                 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);
2914                                 }
2915                                 else
2916                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
2917                                 // free the image
2918                                 Mem_Free(image_buffer);
2919                         }
2920                 }
2921         }
2922         // if a cubemap loaded, upload it
2923         if (cubemappixels)
2924         {
2925                 if (developer_loading.integer)
2926                         Con_Printf("loading cubemap \"%s\"\n", basename);
2927
2928                 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);
2929                 Mem_Free(cubemappixels);
2930         }
2931         else
2932         {
2933                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
2934                 if (developer_loading.integer)
2935                 {
2936                         Con_Printf("(tried tried images ");
2937                         for (j = 0;j < 3;j++)
2938                                 for (i = 0;i < 6;i++)
2939                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
2940                         Con_Print(" and was unable to find any of them).\n");
2941                 }
2942         }
2943         return cubemaptexture;
2944 }
2945
2946 rtexture_t *R_GetCubemap(const char *basename)
2947 {
2948         int i;
2949         for (i = 0;i < r_texture_numcubemaps;i++)
2950                 if (r_texture_cubemaps[i] != NULL)
2951                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
2952                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
2953         if (i >= MAX_CUBEMAPS || !r_main_mempool)
2954                 return r_texture_whitecube;
2955         r_texture_numcubemaps++;
2956         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
2957         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
2958         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
2959         return r_texture_cubemaps[i]->texture;
2960 }
2961
2962 static void R_Main_FreeViewCache(void)
2963 {
2964         if (r_refdef.viewcache.entityvisible)
2965                 Mem_Free(r_refdef.viewcache.entityvisible);
2966         if (r_refdef.viewcache.world_pvsbits)
2967                 Mem_Free(r_refdef.viewcache.world_pvsbits);
2968         if (r_refdef.viewcache.world_leafvisible)
2969                 Mem_Free(r_refdef.viewcache.world_leafvisible);
2970         if (r_refdef.viewcache.world_surfacevisible)
2971                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2972         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2973 }
2974
2975 static void R_Main_ResizeViewCache(void)
2976 {
2977         int numentities = r_refdef.scene.numentities;
2978         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2979         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2980         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2981         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2982         if (r_refdef.viewcache.maxentities < numentities)
2983         {
2984                 r_refdef.viewcache.maxentities = numentities;
2985                 if (r_refdef.viewcache.entityvisible)
2986                         Mem_Free(r_refdef.viewcache.entityvisible);
2987                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2988         }
2989         if (r_refdef.viewcache.world_numclusters != numclusters)
2990         {
2991                 r_refdef.viewcache.world_numclusters = numclusters;
2992                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2993                 if (r_refdef.viewcache.world_pvsbits)
2994                         Mem_Free(r_refdef.viewcache.world_pvsbits);
2995                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2996         }
2997         if (r_refdef.viewcache.world_numleafs != numleafs)
2998         {
2999                 r_refdef.viewcache.world_numleafs = numleafs;
3000                 if (r_refdef.viewcache.world_leafvisible)
3001                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3002                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3003         }
3004         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3005         {
3006                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3007                 if (r_refdef.viewcache.world_surfacevisible)
3008                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3009                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3010         }
3011 }
3012
3013 extern rtexture_t *loadingscreentexture;
3014 static void gl_main_start(void)
3015 {
3016         loadingscreentexture = NULL;
3017         r_texture_blanknormalmap = NULL;
3018         r_texture_white = NULL;
3019         r_texture_grey128 = NULL;
3020         r_texture_black = NULL;
3021         r_texture_whitecube = NULL;
3022         r_texture_normalizationcube = NULL;
3023         r_texture_fogattenuation = NULL;
3024         r_texture_fogheighttexture = NULL;
3025         r_texture_gammaramps = NULL;
3026         r_texture_numcubemaps = 0;
3027         r_uniformbufferalignment = 32;
3028
3029         r_loaddds = r_texture_dds_load.integer != 0;
3030         r_savedds = vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3031
3032         switch(vid.renderpath)
3033         {
3034         case RENDERPATH_GL32:
3035         case RENDERPATH_GLES2:
3036                 Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS);
3037                 Cvar_SetValueQuick(&gl_combine, 1);
3038                 Cvar_SetValueQuick(&r_glsl, 1);
3039                 r_loadnormalmap = true;
3040                 r_loadgloss = true;
3041                 r_loadfog = false;
3042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3043                 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3044 #endif
3045                 break;
3046         }
3047
3048         R_AnimCache_Free();
3049         R_FrameData_Reset();
3050         R_BufferData_Reset();
3051
3052         r_numqueries = 0;
3053         r_maxqueries = 0;
3054         memset(r_queries, 0, sizeof(r_queries));
3055
3056         r_qwskincache = NULL;
3057         r_qwskincache_size = 0;
3058
3059         // due to caching of texture_t references, the collision cache must be reset
3060         Collision_Cache_Reset(true);
3061
3062         // set up r_skinframe loading system for textures
3063         memset(&r_skinframe, 0, sizeof(r_skinframe));
3064         r_skinframe.loadsequence = 1;
3065         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3066
3067         r_main_texturepool = R_AllocTexturePool();
3068         R_BuildBlankTextures();
3069         R_BuildNoTexture();
3070         R_BuildWhiteCube();
3071         R_BuildNormalizationCube();
3072         r_texture_fogattenuation = NULL;
3073         r_texture_fogheighttexture = NULL;
3074         r_texture_gammaramps = NULL;
3075         //r_texture_fogintensity = NULL;
3076         memset(&r_fb, 0, sizeof(r_fb));
3077         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
3078         r_glsl_permutation = NULL;
3079         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3080         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3081         memset(&r_svbsp, 0, sizeof (r_svbsp));
3082
3083         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3084         r_texture_numcubemaps = 0;
3085
3086         r_refdef.fogmasktable_density = 0;
3087
3088 #ifdef __ANDROID__
3089         // For Steelstorm Android
3090         // FIXME CACHE the program and reload
3091         // FIXME see possible combinations for SS:BR android
3092         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
3093         R_SetupShader_SetPermutationGLSL(0, 12);
3094         R_SetupShader_SetPermutationGLSL(0, 13);
3095         R_SetupShader_SetPermutationGLSL(0, 8388621);
3096         R_SetupShader_SetPermutationGLSL(3, 0);
3097         R_SetupShader_SetPermutationGLSL(3, 2048);
3098         R_SetupShader_SetPermutationGLSL(5, 0);
3099         R_SetupShader_SetPermutationGLSL(5, 2);
3100         R_SetupShader_SetPermutationGLSL(5, 2048);
3101         R_SetupShader_SetPermutationGLSL(5, 8388608);
3102         R_SetupShader_SetPermutationGLSL(11, 1);
3103         R_SetupShader_SetPermutationGLSL(11, 2049);
3104         R_SetupShader_SetPermutationGLSL(11, 8193);
3105         R_SetupShader_SetPermutationGLSL(11, 10241);
3106         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
3107 #endif
3108 }
3109
3110 static void gl_main_shutdown(void)
3111 {
3112         R_RenderTarget_FreeUnused(true);
3113         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
3114         R_AnimCache_Free();
3115         R_FrameData_Reset();
3116         R_BufferData_Reset();
3117
3118         R_Main_FreeViewCache();
3119
3120         switch(vid.renderpath)
3121         {
3122         case RENDERPATH_GL32:
3123         case RENDERPATH_GLES2:
3124 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
3125                 if (r_maxqueries)
3126                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3127 #endif
3128                 break;
3129         }
3130
3131         r_numqueries = 0;
3132         r_maxqueries = 0;
3133         memset(r_queries, 0, sizeof(r_queries));
3134
3135         r_qwskincache = NULL;
3136         r_qwskincache_size = 0;
3137
3138         // clear out the r_skinframe state
3139         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3140         memset(&r_skinframe, 0, sizeof(r_skinframe));
3141
3142         if (r_svbsp.nodes)
3143                 Mem_Free(r_svbsp.nodes);
3144         memset(&r_svbsp, 0, sizeof (r_svbsp));
3145         R_FreeTexturePool(&r_main_texturepool);
3146         loadingscreentexture = NULL;
3147         r_texture_blanknormalmap = NULL;
3148         r_texture_white = NULL;
3149         r_texture_grey128 = NULL;
3150         r_texture_black = NULL;
3151         r_texture_whitecube = NULL;
3152         r_texture_normalizationcube = NULL;
3153         r_texture_fogattenuation = NULL;
3154         r_texture_fogheighttexture = NULL;
3155         r_texture_gammaramps = NULL;
3156         r_texture_numcubemaps = 0;
3157         //r_texture_fogintensity = NULL;
3158         memset(&r_fb, 0, sizeof(r_fb));
3159         R_GLSL_Restart_f();
3160
3161         r_glsl_permutation = NULL;
3162         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3163         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3164 }
3165
3166 static void gl_main_newmap(void)
3167 {
3168         // FIXME: move this code to client
3169         char *entities, entname[MAX_QPATH];
3170         if (r_qwskincache)
3171                 Mem_Free(r_qwskincache);
3172         r_qwskincache = NULL;
3173         r_qwskincache_size = 0;
3174         if (cl.worldmodel)
3175         {
3176                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3177                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3178                 {
3179                         CL_ParseEntityLump(entities);
3180                         Mem_Free(entities);
3181                         return;
3182                 }
3183                 if (cl.worldmodel->brush.entities)
3184                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3185         }
3186         R_Main_FreeViewCache();
3187
3188         R_FrameData_Reset();
3189         R_BufferData_Reset();
3190 }
3191
3192 void GL_Main_Init(void)
3193 {
3194         int i;
3195         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3196         R_InitShaderModeInfo();
3197
3198         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3199         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3200         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3201         if (gamemode == GAME_NEHAHRA)
3202         {
3203                 Cvar_RegisterVariable (&gl_fogenable);
3204                 Cvar_RegisterVariable (&gl_fogdensity);
3205                 Cvar_RegisterVariable (&gl_fogred);
3206                 Cvar_RegisterVariable (&gl_foggreen);
3207                 Cvar_RegisterVariable (&gl_fogblue);
3208                 Cvar_RegisterVariable (&gl_fogstart);
3209                 Cvar_RegisterVariable (&gl_fogend);
3210                 Cvar_RegisterVariable (&gl_skyclip);
3211         }
3212         Cvar_RegisterVariable(&r_motionblur);
3213         Cvar_RegisterVariable(&r_damageblur);
3214         Cvar_RegisterVariable(&r_motionblur_averaging);
3215         Cvar_RegisterVariable(&r_motionblur_randomize);
3216         Cvar_RegisterVariable(&r_motionblur_minblur);
3217         Cvar_RegisterVariable(&r_motionblur_maxblur);
3218         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
3219         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
3220         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
3221         Cvar_RegisterVariable(&r_motionblur_mousefactor);
3222         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
3223         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
3224         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3225         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3226         Cvar_RegisterVariable(&r_equalize_entities_by);
3227         Cvar_RegisterVariable(&r_equalize_entities_to);
3228         Cvar_RegisterVariable(&r_depthfirst);
3229         Cvar_RegisterVariable(&r_useinfinitefarclip);
3230         Cvar_RegisterVariable(&r_farclip_base);
3231         Cvar_RegisterVariable(&r_farclip_world);
3232         Cvar_RegisterVariable(&r_nearclip);
3233         Cvar_RegisterVariable(&r_deformvertexes);
3234         Cvar_RegisterVariable(&r_transparent);
3235         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
3236         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
3237         Cvar_RegisterVariable(&r_transparent_useplanardistance);
3238         Cvar_RegisterVariable(&r_showoverdraw);
3239         Cvar_RegisterVariable(&r_showbboxes);
3240         Cvar_RegisterVariable(&r_showbboxes_client);
3241         Cvar_RegisterVariable(&r_showsurfaces);
3242         Cvar_RegisterVariable(&r_showtris);
3243         Cvar_RegisterVariable(&r_shownormals);
3244         Cvar_RegisterVariable(&r_showlighting);
3245         Cvar_RegisterVariable(&r_showcollisionbrushes);
3246         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3247         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3248         Cvar_RegisterVariable(&r_showdisabledepthtest);
3249         Cvar_RegisterVariable(&r_showspriteedges);
3250         Cvar_RegisterVariable(&r_showparticleedges);
3251         Cvar_RegisterVariable(&r_drawportals);
3252         Cvar_RegisterVariable(&r_drawentities);
3253         Cvar_RegisterVariable(&r_draw2d);
3254         Cvar_RegisterVariable(&r_drawworld);
3255         Cvar_RegisterVariable(&r_cullentities_trace);
3256         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
3257         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3258         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3259         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3260         Cvar_RegisterVariable(&r_cullentities_trace_expand);
3261         Cvar_RegisterVariable(&r_cullentities_trace_pad);
3262         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3263         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
3264         Cvar_RegisterVariable(&r_sortentities);
3265         Cvar_RegisterVariable(&r_drawviewmodel);
3266         Cvar_RegisterVariable(&r_drawexteriormodel);
3267         Cvar_RegisterVariable(&r_speeds);
3268         Cvar_RegisterVariable(&r_fullbrights);
3269         Cvar_RegisterVariable(&r_wateralpha);
3270         Cvar_RegisterVariable(&r_dynamic);
3271         Cvar_RegisterVariable(&r_fakelight);
3272         Cvar_RegisterVariable(&r_fakelight_intensity);
3273         Cvar_RegisterVariable(&r_fullbright_directed);
3274         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
3275         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
3276         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
3277         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
3278         Cvar_RegisterVariable(&r_fullbright);
3279         Cvar_RegisterVariable(&r_shadows);
3280         Cvar_RegisterVariable(&r_shadows_darken);
3281         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3282         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3283         Cvar_RegisterVariable(&r_shadows_throwdistance);
3284         Cvar_RegisterVariable(&r_shadows_throwdirection);
3285         Cvar_RegisterVariable(&r_shadows_focus);
3286         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
3287         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
3288         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3289         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3290         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3291         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3292         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3293         Cvar_RegisterVariable(&r_fog_exp2);
3294         Cvar_RegisterVariable(&r_fog_clear);
3295         Cvar_RegisterVariable(&r_drawfog);
3296         Cvar_RegisterVariable(&r_transparentdepthmasking);
3297         Cvar_RegisterVariable(&r_transparent_sortmindist);
3298         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
3299         Cvar_RegisterVariable(&r_transparent_sortarraysize);
3300         Cvar_RegisterVariable(&r_texture_dds_load);
3301         Cvar_RegisterVariable(&r_texture_dds_save);
3302         Cvar_RegisterVariable(&r_textureunits);
3303         Cvar_RegisterVariable(&gl_combine);
3304         Cvar_RegisterVariable(&r_usedepthtextures);
3305         Cvar_RegisterVariable(&r_viewfbo);
3306         Cvar_RegisterVariable(&r_rendertarget_debug);
3307         Cvar_RegisterVariable(&r_viewscale);
3308         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
3309         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
3310         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
3311         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
3312         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
3313         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
3314         Cvar_RegisterVariable(&r_glsl);
3315         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3316         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3317         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
3318         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3319         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
3320         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
3321         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3322         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
3323         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
3324         Cvar_RegisterVariable(&r_glsl_postprocess);
3325         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3326         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3327         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3328         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3329         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
3330         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
3331         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
3332         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
3333         Cvar_RegisterVariable(&r_celshading);
3334         Cvar_RegisterVariable(&r_celoutlines);
3335
3336         Cvar_RegisterVariable(&r_water);
3337         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
3338         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3339         Cvar_RegisterVariable(&r_water_clippingplanebias);
3340         Cvar_RegisterVariable(&r_water_refractdistort);
3341         Cvar_RegisterVariable(&r_water_reflectdistort);
3342         Cvar_RegisterVariable(&r_water_scissormode);
3343         Cvar_RegisterVariable(&r_water_lowquality);
3344         Cvar_RegisterVariable(&r_water_hideplayer);
3345
3346         Cvar_RegisterVariable(&r_lerpsprites);
3347         Cvar_RegisterVariable(&r_lerpmodels);
3348         Cvar_RegisterVariable(&r_lerplightstyles);
3349         Cvar_RegisterVariable(&r_waterscroll);
3350         Cvar_RegisterVariable(&r_bloom);
3351         Cvar_RegisterVariable(&r_bloom_colorscale);
3352         Cvar_RegisterVariable(&r_bloom_brighten);
3353         Cvar_RegisterVariable(&r_bloom_blur);
3354         Cvar_RegisterVariable(&r_bloom_resolution);
3355         Cvar_RegisterVariable(&r_bloom_colorexponent);
3356         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3357         Cvar_RegisterVariable(&r_bloom_scenebrightness);
3358         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3359         Cvar_RegisterVariable(&r_hdr_glowintensity);
3360         Cvar_RegisterVariable(&r_hdr_irisadaptation);
3361         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
3362         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
3363         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
3364         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
3365         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
3366         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
3367         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
3368         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3369         Cvar_RegisterVariable(&developer_texturelogging);
3370         Cvar_RegisterVariable(&gl_lightmaps);
3371         Cvar_RegisterVariable(&r_test);
3372         Cvar_RegisterVariable(&r_batch_multidraw);
3373         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
3374         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
3375         Cvar_RegisterVariable(&r_glsl_skeletal);
3376         Cvar_RegisterVariable(&r_glsl_saturation);
3377         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
3378         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
3379         Cvar_RegisterVariable(&r_framedatasize);
3380         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
3381                 Cvar_RegisterVariable(&r_buffermegs[i]);
3382         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
3383         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3384                 Cvar_SetValue("r_fullbrights", 0);
3385 #ifdef DP_MOBILETOUCH
3386         // GLES devices have terrible depth precision in general, so...
3387         Cvar_SetValueQuick(&r_nearclip, 4);
3388         Cvar_SetValueQuick(&r_farclip_base, 4096);
3389         Cvar_SetValueQuick(&r_farclip_world, 0);
3390         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
3391 #endif
3392         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
3393 }
3394
3395 void Render_Init(void)
3396 {
3397         gl_backend_init();
3398         R_Textures_Init();
3399         GL_Main_Init();
3400         Font_Init();
3401         GL_Draw_Init();
3402         R_Shadow_Init();
3403         R_Sky_Init();
3404         GL_Surf_Init();
3405         Sbar_Init();
3406         R_Particles_Init();
3407         R_Explosion_Init();
3408         R_LightningBeams_Init();
3409         Mod_RenderInit();
3410 }
3411
3412 /*
3413 ===============
3414 GL_Init
3415 ===============
3416 */
3417 #ifndef USE_GLES2
3418 extern char *ENGINE_EXTENSIONS;
3419 void GL_Init (void)
3420 {
3421         gl_renderer = (const char *)qglGetString(GL_RENDERER);
3422         gl_vendor = (const char *)qglGetString(GL_VENDOR);
3423         gl_version = (const char *)qglGetString(GL_VERSION);
3424         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3425
3426         if (!gl_extensions)
3427                 gl_extensions = "";
3428         if (!gl_platformextensions)
3429                 gl_platformextensions = "";
3430
3431         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3432         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3433         Con_Printf("GL_VERSION: %s\n", gl_version);
3434         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3435         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3436
3437         VID_CheckExtensions();
3438
3439         // LordHavoc: report supported extensions
3440 #ifdef CONFIG_MENU
3441         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3442 #else
3443         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
3444 #endif
3445
3446         // clear to black (loading plaque will be seen over this)
3447         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
3448 }
3449 #endif
3450
3451 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3452 {
3453         int i;
3454         mplane_t *p;
3455         if (r_trippy.integer)
3456                 return false;
3457         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3458         {
3459                 p = r_refdef.view.frustum + i;
3460                 switch(p->signbits)
3461                 {
3462                 default:
3463                 case 0:
3464                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3465                                 return true;
3466                         break;
3467                 case 1:
3468                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3469                                 return true;
3470                         break;
3471                 case 2:
3472                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3473                                 return true;
3474                         break;
3475                 case 3:
3476                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3477                                 return true;
3478                         break;
3479                 case 4:
3480                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3481                                 return true;
3482                         break;
3483                 case 5:
3484                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3485                                 return true;
3486                         break;
3487                 case 6:
3488                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3489                                 return true;
3490                         break;
3491                 case 7:
3492                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3493                                 return true;
3494                         break;
3495                 }
3496         }
3497         return false;
3498 }
3499
3500 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3501 {
3502         int i;
3503         const mplane_t *p;
3504         if (r_trippy.integer)
3505                 return false;
3506         for (i = 0;i < numplanes;i++)
3507         {
3508                 p = planes + i;
3509                 switch(p->signbits)
3510                 {
3511                 default:
3512                 case 0:
3513                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3514                                 return true;
3515                         break;
3516                 case 1:
3517                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3518                                 return true;
3519                         break;
3520                 case 2:
3521                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3522                                 return true;
3523                         break;
3524                 case 3:
3525                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3526                                 return true;
3527                         break;
3528                 case 4:
3529                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3530                                 return true;
3531                         break;
3532                 case 5:
3533                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3534                                 return true;
3535                         break;
3536                 case 6:
3537                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3538                                 return true;
3539                         break;
3540                 case 7:
3541                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3542                                 return true;
3543                         break;
3544                 }
3545         }
3546         return false;
3547 }
3548
3549 //==================================================================================
3550
3551 // LordHavoc: this stores temporary data used within the same frame
3552
3553 typedef struct r_framedata_mem_s
3554 {
3555         struct r_framedata_mem_s *purge; // older mem block to free on next frame
3556         size_t size; // how much usable space
3557         size_t current; // how much space in use
3558         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
3559         size_t wantedsize; // how much space was allocated
3560         unsigned char *data; // start of real data (16byte aligned)
3561 }
3562 r_framedata_mem_t;
3563
3564 static r_framedata_mem_t *r_framedata_mem;
3565
3566 void R_FrameData_Reset(void)
3567 {
3568         while (r_framedata_mem)
3569         {
3570                 r_framedata_mem_t *next = r_framedata_mem->purge;
3571                 Mem_Free(r_framedata_mem);
3572                 r_framedata_mem = next;
3573         }
3574 }
3575
3576 static void R_FrameData_Resize(qboolean mustgrow)
3577 {
3578         size_t wantedsize;
3579         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3580         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
3581         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
3582         {
3583                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
3584                 newmem->wantedsize = wantedsize;
3585                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
3586                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
3587                 newmem->current = 0;
3588                 newmem->mark = 0;
3589                 newmem->purge = r_framedata_mem;
3590                 r_framedata_mem = newmem;
3591         }
3592 }
3593
3594 void R_FrameData_NewFrame(void)
3595 {
3596         R_FrameData_Resize(false);
3597         if (!r_framedata_mem)
3598                 return;
3599         // if we ran out of space on the last frame, free the old memory now
3600         while (r_framedata_mem->purge)
3601         {
3602                 // repeatedly remove the second item in the list, leaving only head
3603                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
3604                 Mem_Free(r_framedata_mem->purge);
3605                 r_framedata_mem->purge = next;
3606         }
3607         // reset the current mem pointer
3608         r_framedata_mem->current = 0;
3609         r_framedata_mem->mark = 0;
3610 }
3611
3612 void *R_FrameData_Alloc(size_t size)
3613 {
3614         void *data;
3615         float newvalue;
3616
3617         // align to 16 byte boundary - the data pointer is already aligned, so we
3618         // only need to ensure the size of every allocation is also aligned
3619         size = (size + 15) & ~15;
3620
3621         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
3622         {
3623                 // emergency - we ran out of space, allocate more memory
3624                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
3625                 newvalue = r_framedatasize.value * 2.0f;
3626                 // 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
3627                 if (sizeof(size_t) >= 8)
3628                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
3629                 else
3630                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
3631                 // this might not be a growing it, but we'll allocate another buffer every time
3632                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
3633                 R_FrameData_Resize(true);
3634         }
3635
3636         data = r_framedata_mem->data + r_framedata_mem->current;
3637         r_framedata_mem->current += size;
3638
3639         // count the usage for stats
3640         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
3641         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
3642
3643         return (void *)data;
3644 }
3645
3646 void *R_FrameData_Store(size_t size, void *data)
3647 {
3648         void *d = R_FrameData_Alloc(size);
3649         if (d && data)
3650                 memcpy(d, data, size);
3651         return d;
3652 }
3653
3654 void R_FrameData_SetMark(void)
3655 {
3656         if (!r_framedata_mem)
3657                 return;
3658         r_framedata_mem->mark = r_framedata_mem->current;
3659 }
3660
3661 void R_FrameData_ReturnToMark(void)
3662 {
3663         if (!r_framedata_mem)
3664                 return;
3665         r_framedata_mem->current = r_framedata_mem->mark;
3666 }
3667
3668 //==================================================================================
3669
3670 // avoid reusing the same buffer objects on consecutive frames
3671 #define R_BUFFERDATA_CYCLE 3
3672
3673 typedef struct r_bufferdata_buffer_s
3674 {
3675         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
3676         size_t size; // how much usable space
3677         size_t current; // how much space in use
3678         r_meshbuffer_t *buffer; // the buffer itself
3679 }
3680 r_bufferdata_buffer_t;
3681
3682 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
3683 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
3684
3685 /// frees all dynamic buffers
3686 void R_BufferData_Reset(void)
3687 {
3688         int cycle, type;
3689         r_bufferdata_buffer_t **p, *mem;
3690         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
3691         {
3692                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3693                 {
3694                         // free all buffers
3695                         p = &r_bufferdata_buffer[cycle][type];
3696                         while (*p)
3697                         {
3698                                 mem = *p;
3699                                 *p = (*p)->purge;
3700                                 if (mem->buffer)
3701                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3702                                 Mem_Free(mem);
3703                         }
3704                 }
3705         }
3706 }
3707
3708 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
3709 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
3710 {
3711         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3712         size_t size;
3713         float newvalue = r_buffermegs[type].value;
3714
3715         // increase the cvar if we have to (but only if we already have a mem)
3716         if (mustgrow && mem)
3717                 newvalue *= 2.0f;
3718         newvalue = bound(0.25f, newvalue, 256.0f);
3719         while (newvalue * 1024*1024 < minsize)
3720                 newvalue *= 2.0f;
3721
3722         // clamp the cvar to valid range
3723         newvalue = bound(0.25f, newvalue, 256.0f);
3724         if (r_buffermegs[type].value != newvalue)
3725                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
3726
3727         // calculate size in bytes
3728         size = (size_t)(newvalue * 1024*1024);
3729         size = bound(131072, size, 256*1024*1024);
3730
3731         // allocate a new buffer if the size is different (purge old one later)
3732         // or if we were told we must grow the buffer
3733         if (!mem || mem->size != size || mustgrow)
3734         {
3735                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
3736                 mem->size = size;
3737                 mem->current = 0;
3738                 if (type == R_BUFFERDATA_VERTEX)
3739                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
3740                 else if (type == R_BUFFERDATA_INDEX16)
3741                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
3742                 else if (type == R_BUFFERDATA_INDEX32)
3743                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
3744                 else if (type == R_BUFFERDATA_UNIFORM)
3745                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
3746                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
3747                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
3748         }
3749 }
3750
3751 void R_BufferData_NewFrame(void)
3752 {
3753         int type;
3754         r_bufferdata_buffer_t **p, *mem;
3755         // cycle to the next frame's buffers
3756         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
3757         // if we ran out of space on the last time we used these buffers, free the old memory now
3758         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3759         {
3760                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
3761                 {
3762                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
3763                         // free all but the head buffer, this is how we recycle obsolete
3764                         // buffers after they are no longer in use
3765                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
3766                         while (*p)
3767                         {
3768                                 mem = *p;
3769                                 *p = (*p)->purge;
3770                                 if (mem->buffer)
3771                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3772                                 Mem_Free(mem);
3773                         }
3774                         // reset the current offset
3775                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
3776                 }
3777         }
3778 }
3779
3780 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
3781 {
3782         r_bufferdata_buffer_t *mem;
3783         int offset = 0;
3784         int padsize;
3785
3786         *returnbufferoffset = 0;
3787
3788         // align size to a byte boundary appropriate for the buffer type, this
3789         // makes all allocations have aligned start offsets
3790         if (type == R_BUFFERDATA_UNIFORM)
3791                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
3792         else
3793                 padsize = (datasize + 15) & ~15;
3794
3795         // if we ran out of space in this buffer we must allocate a new one
3796         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)
3797                 R_BufferData_Resize(type, true, padsize);
3798
3799         // if the resize did not give us enough memory, fail
3800         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)
3801                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
3802
3803         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3804         offset = (int)mem->current;
3805         mem->current += padsize;
3806
3807         // upload the data to the buffer at the chosen offset
3808         if (offset == 0)
3809                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
3810         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
3811
3812         // count the usage for stats
3813         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
3814         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
3815
3816         // return the buffer offset
3817         *returnbufferoffset = offset;
3818
3819         return mem->buffer;
3820 }
3821
3822 //==================================================================================
3823
3824 // LordHavoc: animcache originally written by Echon, rewritten since then
3825
3826 /**
3827  * Animation cache prevents re-generating mesh data for an animated model
3828  * multiple times in one frame for lighting, shadowing, reflections, etc.
3829  */
3830
3831 void R_AnimCache_Free(void)
3832 {
3833 }
3834
3835 void R_AnimCache_ClearCache(void)
3836 {
3837         int i;
3838         entity_render_t *ent;
3839
3840         for (i = 0;i < r_refdef.scene.numentities;i++)
3841         {
3842                 ent = r_refdef.scene.entities[i];
3843                 ent->animcache_vertex3f = NULL;
3844                 ent->animcache_vertex3f_vertexbuffer = NULL;
3845                 ent->animcache_vertex3f_bufferoffset = 0;
3846                 ent->animcache_normal3f = NULL;
3847                 ent->animcache_normal3f_vertexbuffer = NULL;
3848                 ent->animcache_normal3f_bufferoffset = 0;
3849                 ent->animcache_svector3f = NULL;
3850                 ent->animcache_svector3f_vertexbuffer = NULL;
3851                 ent->animcache_svector3f_bufferoffset = 0;
3852                 ent->animcache_tvector3f = NULL;
3853                 ent->animcache_tvector3f_vertexbuffer = NULL;
3854                 ent->animcache_tvector3f_bufferoffset = 0;
3855                 ent->animcache_skeletaltransform3x4 = NULL;
3856                 ent->animcache_skeletaltransform3x4buffer = NULL;
3857                 ent->animcache_skeletaltransform3x4offset = 0;
3858                 ent->animcache_skeletaltransform3x4size = 0;
3859         }
3860 }
3861
3862 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3863 {
3864         dp_model_t *model = ent->model;
3865         int numvertices;
3866
3867         // see if this ent is worth caching
3868         if (!model || !model->Draw || !model->AnimateVertices)
3869                 return false;
3870         // nothing to cache if it contains no animations and has no skeleton
3871         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
3872                 return false;
3873         // see if it is already cached for gpuskeletal
3874         if (ent->animcache_skeletaltransform3x4)
3875                 return false;
3876         // see if it is already cached as a mesh
3877         if (ent->animcache_vertex3f)
3878         {
3879                 // check if we need to add normals or tangents
3880                 if (ent->animcache_normal3f)
3881                         wantnormals = false;
3882                 if (ent->animcache_svector3f)
3883                         wanttangents = false;
3884                 if (!wantnormals && !wanttangents)
3885                         return false;
3886         }
3887
3888         // check which kind of cache we need to generate
3889         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
3890         {
3891                 // cache the skeleton so the vertex shader can use it
3892                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
3893                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
3894                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
3895                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
3896                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
3897                 // note: this can fail if the buffer is at the grow limit
3898                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
3899                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
3900         }
3901         else if (ent->animcache_vertex3f)
3902         {
3903                 // mesh was already cached but we may need to add normals/tangents
3904                 // (this only happens with multiple views, reflections, cameras, etc)
3905                 if (wantnormals || wanttangents)
3906                 {
3907                         numvertices = model->surfmesh.num_vertices;
3908                         if (wantnormals)
3909                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3910                         if (wanttangents)
3911                         {
3912                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3913                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3914                         }
3915                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3916                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3917                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3918                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3919                 }
3920         }
3921         else
3922         {
3923                 // generate mesh cache
3924                 numvertices = model->surfmesh.num_vertices;
3925                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3926                 if (wantnormals)
3927                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3928                 if (wanttangents)
3929                 {
3930                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3931                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3932                 }
3933                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3934                 if (wantnormals || wanttangents)
3935                 {
3936                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3937                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3938                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3939                 }
3940                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
3941                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
3942                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
3943         }
3944         return true;
3945 }
3946
3947 void R_AnimCache_CacheVisibleEntities(void)
3948 {
3949         int i;
3950
3951         // TODO: thread this
3952         // NOTE: R_PrepareRTLights() also caches entities
3953
3954         for (i = 0;i < r_refdef.scene.numentities;i++)
3955                 if (r_refdef.viewcache.entityvisible[i])
3956                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], true, true);
3957 }
3958
3959 //==================================================================================
3960
3961 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)
3962 {
3963         int i;
3964         vec3_t eyemins, eyemaxs;
3965         vec3_t boxmins, boxmaxs;
3966         vec3_t padmins, padmaxs;
3967         vec3_t start;
3968         vec3_t end;
3969         dp_model_t *model = r_refdef.scene.worldmodel;
3970         static vec3_t positions[] = {
3971                 { 0.5f, 0.5f, 0.5f },
3972                 { 0.0f, 0.0f, 0.0f },
3973                 { 0.0f, 0.0f, 1.0f },
3974                 { 0.0f, 1.0f, 0.0f },
3975                 { 0.0f, 1.0f, 1.0f },
3976                 { 1.0f, 0.0f, 0.0f },
3977                 { 1.0f, 0.0f, 1.0f },
3978                 { 1.0f, 1.0f, 0.0f },
3979                 { 1.0f, 1.0f, 1.0f },
3980         };
3981
3982         // sample count can be set to -1 to skip this logic, for flicker-prone objects
3983         if (numsamples < 0)
3984                 return true;
3985
3986         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
3987         if (!r_refdef.view.usevieworiginculling)
3988                 return true;
3989
3990         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
3991                 return true;
3992
3993         // expand the eye box a little
3994         eyemins[0] = eye[0] - eyejitter;
3995         eyemaxs[0] = eye[0] + eyejitter;
3996         eyemins[1] = eye[1] - eyejitter;
3997         eyemaxs[1] = eye[1] + eyejitter;
3998         eyemins[2] = eye[2] - eyejitter;
3999         eyemaxs[2] = eye[2] + eyejitter;
4000         // expand the box a little
4001         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
4002         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
4003         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
4004         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
4005         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
4006         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
4007         // make an even larger box for the acceptable area
4008         padmins[0] = boxmins[0] - pad;
4009         padmaxs[0] = boxmaxs[0] + pad;
4010         padmins[1] = boxmins[1] - pad;
4011         padmaxs[1] = boxmaxs[1] + pad;
4012         padmins[2] = boxmins[2] - pad;
4013         padmaxs[2] = boxmaxs[2] + pad;
4014
4015         // return true if eye overlaps enlarged box
4016         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
4017                 return true;
4018
4019         // try specific positions in the box first - note that these can be cached
4020         if (r_cullentities_trace_entityocclusion.integer)
4021         {
4022                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
4023                 {
4024                         VectorCopy(eye, start);
4025                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
4026                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
4027                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
4028                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
4029                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
4030                         // not picky - if the trace ended anywhere in the box we're good
4031                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
4032                                 return true;
4033                 }
4034         }
4035         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
4036                 return true;
4037
4038         // try various random positions
4039         for (i = 0; i < numsamples; i++)
4040         {
4041                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
4042                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4043                 if (r_cullentities_trace_entityocclusion.integer)
4044                 {
4045                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
4046                         // not picky - if the trace ended anywhere in the box we're good
4047                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
4048                                 return true;
4049                 }
4050                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
4051                         return true;
4052         }
4053
4054         return false;
4055 }
4056
4057
4058 static void R_View_UpdateEntityVisible (void)
4059 {
4060         int i;
4061         int renderimask;
4062         int samples;
4063         entity_render_t *ent;
4064
4065         if (r_refdef.envmap || r_fb.water.hideplayer)
4066                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
4067         else if (chase_active.integer || r_fb.water.renderingscene)
4068                 renderimask = RENDER_VIEWMODEL;
4069         else
4070                 renderimask = RENDER_EXTERIORMODEL;
4071         if (!r_drawviewmodel.integer)
4072                 renderimask |= RENDER_VIEWMODEL;
4073         if (!r_drawexteriormodel.integer)
4074                 renderimask |= RENDER_EXTERIORMODEL;
4075         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4076         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4077         {
4078                 // worldmodel can check visibility
4079                 for (i = 0;i < r_refdef.scene.numentities;i++)
4080                 {
4081                         ent = r_refdef.scene.entities[i];
4082                         if (!(ent->flags & renderimask))
4083                         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)))
4084                         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))
4085                                 r_refdef.viewcache.entityvisible[i] = true;
4086                 }
4087         }
4088         else
4089         {
4090                 // no worldmodel or it can't check visibility
4091                 for (i = 0;i < r_refdef.scene.numentities;i++)
4092                 {
4093                         ent = r_refdef.scene.entities[i];
4094                         if (!(ent->flags & renderimask))
4095                         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)))
4096                                 r_refdef.viewcache.entityvisible[i] = true;
4097                 }
4098         }
4099         if (r_cullentities_trace.integer)
4100         {
4101                 for (i = 0;i < r_refdef.scene.numentities;i++)
4102                 {
4103                         if (!r_refdef.viewcache.entityvisible[i])
4104                                 continue;
4105                         ent = r_refdef.scene.entities[i];
4106                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4107                         {
4108                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
4109                                 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))
4110                                         ent->last_trace_visibility = realtime;
4111                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4112                                         r_refdef.viewcache.entityvisible[i] = 0;
4113                         }
4114                 }
4115         }
4116 }
4117
4118 /// only used if skyrendermasked, and normally returns false
4119 static int R_DrawBrushModelsSky (void)
4120 {
4121         int i, sky;
4122         entity_render_t *ent;
4123
4124         sky = false;
4125         for (i = 0;i < r_refdef.scene.numentities;i++)
4126         {
4127                 if (!r_refdef.viewcache.entityvisible[i])
4128                         continue;
4129                 ent = r_refdef.scene.entities[i];
4130                 if (!ent->model || !ent->model->DrawSky)
4131                         continue;
4132                 ent->model->DrawSky(ent);
4133                 sky = true;
4134         }
4135         return sky;
4136 }
4137
4138 static void R_DrawNoModel(entity_render_t *ent);
4139 static void R_DrawModels(void)
4140 {
4141         int i;
4142         entity_render_t *ent;
4143
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                 r_refdef.stats[r_stat_entities]++;
4150                 /*
4151                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4152                 {
4153                         vec3_t f, l, u, o;
4154                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4155                         Con_Printf("R_DrawModels\n");
4156                         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]);
4157                         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);
4158                         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);
4159                 }
4160                 */
4161                 if (ent->model && ent->model->Draw != NULL)
4162                         ent->model->Draw(ent);
4163                 else
4164                         R_DrawNoModel(ent);
4165         }
4166 }
4167
4168 static void R_DrawModelsDepth(void)
4169 {
4170         int i;
4171         entity_render_t *ent;
4172
4173         for (i = 0;i < r_refdef.scene.numentities;i++)
4174         {
4175                 if (!r_refdef.viewcache.entityvisible[i])
4176                         continue;
4177                 ent = r_refdef.scene.entities[i];
4178                 if (ent->model && ent->model->DrawDepth != NULL)
4179                         ent->model->DrawDepth(ent);
4180         }
4181 }
4182
4183 static void R_DrawModelsDebug(void)
4184 {
4185         int i;
4186         entity_render_t *ent;
4187
4188         for (i = 0;i < r_refdef.scene.numentities;i++)
4189         {
4190                 if (!r_refdef.viewcache.entityvisible[i])
4191                         continue;
4192                 ent = r_refdef.scene.entities[i];
4193                 if (ent->model && ent->model->DrawDebug != NULL)
4194                         ent->model->DrawDebug(ent);
4195         }
4196 }
4197
4198 static void R_DrawModelsAddWaterPlanes(void)
4199 {
4200         int i;
4201         entity_render_t *ent;
4202
4203         for (i = 0;i < r_refdef.scene.numentities;i++)
4204         {
4205                 if (!r_refdef.viewcache.entityvisible[i])
4206                         continue;
4207                 ent = r_refdef.scene.entities[i];
4208                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4209                         ent->model->DrawAddWaterPlanes(ent);
4210         }
4211 }
4212
4213 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}};
4214
4215 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4216 {
4217         if (r_hdr_irisadaptation.integer)
4218         {
4219                 vec3_t p;
4220                 vec3_t ambient;
4221                 vec3_t diffuse;
4222                 vec3_t diffusenormal;
4223                 vec3_t forward;
4224                 vec_t brightness = 0.0f;
4225                 vec_t goal;
4226                 vec_t current;
4227                 vec_t d;
4228                 int c;
4229                 VectorCopy(r_refdef.view.forward, forward);
4230                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
4231                 {
4232                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
4233                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
4234                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
4235                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
4236                         d = DotProduct(forward, diffusenormal);
4237                         brightness += VectorLength(ambient);
4238                         if (d > 0)
4239                                 brightness += d * VectorLength(diffuse);
4240                 }
4241                 brightness *= 1.0f / c;
4242                 brightness += 0.00001f; // make sure it's never zero
4243                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4244                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4245                 current = r_hdr_irisadaptation_value.value;
4246                 if (current < goal)
4247                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
4248                 else if (current > goal)
4249                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
4250                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4251                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4252         }
4253         else if (r_hdr_irisadaptation_value.value != 1.0f)
4254                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4255 }
4256
4257 static void R_View_SetFrustum(const int *scissor)
4258 {
4259         int i;
4260         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4261         vec3_t forward, left, up, origin, v;
4262
4263         if(scissor)
4264         {
4265                 // flipped x coordinates (because x points left here)
4266                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4267                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4268                 // non-flipped y coordinates
4269                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4270                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4271         }
4272
4273         // we can't trust r_refdef.view.forward and friends in reflected scenes
4274         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4275
4276 #if 0
4277         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4278         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4279         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4280         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4281         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4282         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4283         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4284         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4285         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4286         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4287         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4288         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4289 #endif
4290
4291 #if 0
4292         zNear = r_refdef.nearclip;
4293         nudge = 1.0 - 1.0 / (1<<23);
4294         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4295         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4296         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4297         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4298         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4299         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4300         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4301         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4302 #endif
4303
4304
4305
4306 #if 0
4307         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4308         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4309         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4310         r_refdef.view.frustum[0].dist = m[15] - m[12];
4311
4312         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4313         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4314         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4315         r_refdef.view.frustum[1].dist = m[15] + m[12];
4316
4317         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4318         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4319         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4320         r_refdef.view.frustum[2].dist = m[15] - m[13];
4321
4322         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4323         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4324         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4325         r_refdef.view.frustum[3].dist = m[15] + m[13];
4326
4327         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4328         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4329         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4330         r_refdef.view.frustum[4].dist = m[15] - m[14];
4331
4332         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4333         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4334         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4335         r_refdef.view.frustum[5].dist = m[15] + m[14];
4336 #endif
4337
4338         if (r_refdef.view.useperspective)
4339         {
4340                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4341                 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]);
4342                 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]);
4343                 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]);
4344                 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]);
4345
4346                 // then the normals from the corners relative to origin
4347                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4348                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4349                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4350                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4351
4352                 // in a NORMAL view, forward cross left == up
4353                 // in a REFLECTED view, forward cross left == down
4354                 // so our cross products above need to be adjusted for a left handed coordinate system
4355                 CrossProduct(forward, left, v);
4356                 if(DotProduct(v, up) < 0)
4357                 {
4358                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4359                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4360                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4361                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4362                 }
4363
4364                 // Leaving those out was a mistake, those were in the old code, and they
4365                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4366                 // I couldn't reproduce it after adding those normalizations. --blub
4367                 VectorNormalize(r_refdef.view.frustum[0].normal);
4368                 VectorNormalize(r_refdef.view.frustum[1].normal);
4369                 VectorNormalize(r_refdef.view.frustum[2].normal);
4370                 VectorNormalize(r_refdef.view.frustum[3].normal);
4371
4372                 // make the corners absolute
4373                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4374                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4375                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4376                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4377
4378                 // one more normal
4379                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4380
4381                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4382                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4383                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4384                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4385                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4386         }
4387         else
4388         {
4389                 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
4390                 VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
4391                 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
4392                 VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
4393                 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
4394                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
4395                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
4396                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
4397                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
4398                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
4399         }
4400         r_refdef.view.numfrustumplanes = 5;
4401
4402         if (r_refdef.view.useclipplane)
4403         {
4404                 r_refdef.view.numfrustumplanes = 6;
4405                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4406         }
4407
4408         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4409                 PlaneClassify(r_refdef.view.frustum + i);
4410
4411         // LordHavoc: note to all quake engine coders, Quake had a special case
4412         // for 90 degrees which assumed a square view (wrong), so I removed it,
4413         // Quake2 has it disabled as well.
4414
4415         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4416         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4417         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4418         //PlaneClassify(&frustum[0]);
4419
4420         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4421         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4422         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4423         //PlaneClassify(&frustum[1]);
4424
4425         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4426         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4427         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4428         //PlaneClassify(&frustum[2]);
4429
4430         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4431         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4432         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4433         //PlaneClassify(&frustum[3]);
4434
4435         // nearclip plane
4436         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4437         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4438         //PlaneClassify(&frustum[4]);
4439 }
4440
4441 static void R_View_UpdateWithScissor(const int *myscissor)
4442 {
4443         R_Main_ResizeViewCache();
4444         R_View_SetFrustum(myscissor);
4445         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4446         R_View_UpdateEntityVisible();
4447 }
4448
4449 static void R_View_Update(void)
4450 {
4451         R_Main_ResizeViewCache();
4452         R_View_SetFrustum(NULL);
4453         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4454         R_View_UpdateEntityVisible();
4455 }
4456
4457 float viewscalefpsadjusted = 1.0f;
4458
4459 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
4460 {
4461         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
4462         scale = bound(0.03125f, scale, 1.0f);
4463         *outwidth = (int)ceil(width * scale);
4464         *outheight = (int)ceil(height * scale);
4465 }
4466
4467 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4468 {
4469         const float *customclipplane = NULL;
4470         float plane[4];
4471         int /*rtwidth,*/ rtheight;
4472         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4473         {
4474                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
4475                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4476                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4477                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4478                         dist = r_refdef.view.clipplane.dist;
4479                 plane[0] = r_refdef.view.clipplane.normal[0];
4480                 plane[1] = r_refdef.view.clipplane.normal[1];
4481                 plane[2] = r_refdef.view.clipplane.normal[2];
4482                 plane[3] = -dist;
4483                 customclipplane = plane;
4484         }
4485
4486         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
4487         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
4488
4489         if (!r_refdef.view.useperspective)
4490                 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);
4491         else if (vid.stencil && r_useinfinitefarclip.integer)
4492                 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);
4493         else
4494                 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);
4495         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4496         R_SetViewport(&r_refdef.view.viewport);
4497 }
4498
4499 void R_EntityMatrix(const matrix4x4_t *matrix)
4500 {
4501         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4502         {
4503                 gl_modelmatrixchanged = false;
4504                 gl_modelmatrix = *matrix;
4505                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4506                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4507                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4508                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4509                 CHECKGLERROR
4510                 switch(vid.renderpath)
4511                 {
4512                 case RENDERPATH_GL32:
4513                 case RENDERPATH_GLES2:
4514                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4515                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4516                         break;
4517                 }
4518         }
4519 }
4520
4521 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
4522 {
4523         r_viewport_t viewport;
4524
4525         CHECKGLERROR
4526
4527         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4528         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
4529         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4530         R_SetViewport(&viewport);
4531         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4532         GL_Color(1, 1, 1, 1);
4533         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4534         GL_BlendFunc(GL_ONE, GL_ZERO);
4535         GL_ScissorTest(false);
4536         GL_DepthMask(false);
4537         GL_DepthRange(0, 1);
4538         GL_DepthTest(false);
4539         GL_DepthFunc(GL_LEQUAL);
4540         R_EntityMatrix(&identitymatrix);
4541         R_Mesh_ResetTextureState();
4542         GL_PolygonOffset(0, 0);
4543         switch(vid.renderpath)
4544         {
4545         case RENDERPATH_GL32:
4546         case RENDERPATH_GLES2:
4547                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4548                 break;
4549         }
4550         GL_CullFace(GL_NONE);
4551
4552         CHECKGLERROR
4553 }
4554
4555 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4556 {
4557         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
4558 }
4559
4560 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4561 {
4562         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
4563         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4564         GL_Color(1, 1, 1, 1);
4565         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4566         GL_BlendFunc(GL_ONE, GL_ZERO);
4567         GL_ScissorTest(true);
4568         GL_DepthMask(true);
4569         GL_DepthRange(0, 1);
4570         GL_DepthTest(true);
4571         GL_DepthFunc(GL_LEQUAL);
4572         R_EntityMatrix(&identitymatrix);
4573         R_Mesh_ResetTextureState();
4574         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4575         switch(vid.renderpath)
4576         {
4577         case RENDERPATH_GL32:
4578         case RENDERPATH_GLES2:
4579                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4580                 break;
4581         }
4582         GL_CullFace(r_refdef.view.cullface_back);
4583 }
4584
4585 /*
4586 ================
4587 R_RenderView_UpdateViewVectors
4588 ================
4589 */
4590 void R_RenderView_UpdateViewVectors(void)
4591 {
4592         // break apart the view matrix into vectors for various purposes
4593         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4594         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4595         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4596         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4597         // make an inverted copy of the view matrix for tracking sprites
4598         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4599 }
4600
4601 void R_RenderTarget_FreeUnused(qboolean force)
4602 {
4603         int i, j, end;
4604         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4605         for (i = 0; i < end; i++)
4606         {
4607                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4608                 // free resources for rendertargets that have not been used for a while
4609                 // (note: this check is run after the frame render, so any targets used
4610                 // this frame will not be affected even at low framerates)
4611                 if (r && (realtime - r->lastusetime > 0.2 || force))
4612                 {
4613                         if (r->fbo)
4614                                 R_Mesh_DestroyFramebufferObject(r->fbo);
4615                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
4616                                 if (r->colortexture[j])
4617                                         R_FreeTexture(r->colortexture[j]);
4618                         if (r->depthtexture)
4619                                 R_FreeTexture(r->depthtexture);
4620                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
4621                 }
4622         }
4623 }
4624
4625 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
4626 {
4627         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
4628         x1 = x * iw;
4629         x2 = (x + w) * iw;
4630         y1 = (th - y) * ih;
4631         y2 = (th - y - h) * ih;
4632         texcoord2f[0] = x1;
4633         texcoord2f[2] = x2;
4634         texcoord2f[4] = x2;
4635         texcoord2f[6] = x1;
4636         texcoord2f[1] = y1;
4637         texcoord2f[3] = y1;
4638         texcoord2f[5] = y2;
4639         texcoord2f[7] = y2;
4640 }
4641
4642 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)
4643 {
4644         int i, j, end;
4645         r_rendertarget_t *r = NULL;
4646         char vabuf[256];
4647         // first try to reuse an existing slot if possible
4648         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4649         for (i = 0; i < end; i++)
4650         {
4651                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4652                 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)
4653                         break;
4654         }
4655         if (i == end)
4656         {
4657                 // no unused exact match found, so we have to make one in the first unused slot
4658                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
4659                 r->texturewidth = texturewidth;
4660                 r->textureheight = textureheight;
4661                 r->colortextype[0] = colortextype0;
4662                 r->colortextype[1] = colortextype1;
4663                 r->colortextype[2] = colortextype2;
4664                 r->colortextype[3] = colortextype3;
4665                 r->depthtextype = depthtextype;
4666                 r->depthisrenderbuffer = depthisrenderbuffer;
4667                 for (j = 0; j < 4; j++)
4668                         if (r->colortextype[j])
4669                                 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);
4670                 if (r->depthtextype)
4671                 {
4672                         if (r->depthisrenderbuffer)
4673                                 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);
4674                         else
4675                                 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);
4676                 }
4677                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
4678         }
4679         r_refdef.stats[r_stat_rendertargets_used]++;
4680         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
4681         r->lastusetime = realtime;
4682         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
4683         return r;
4684 }
4685
4686 static void R_Water_StartFrame(void)
4687 {
4688         int waterwidth, waterheight;
4689
4690         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4691                 return;
4692
4693         // set waterwidth and waterheight to the water resolution that will be
4694         // used (often less than the screen resolution for faster rendering)
4695         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4696         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4697         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
4698
4699         if (!r_water.integer || r_showsurfaces.integer)
4700                 waterwidth = waterheight = 0;
4701
4702         // set up variables that will be used in shader setup
4703         r_fb.water.waterwidth = waterwidth;
4704         r_fb.water.waterheight = waterheight;
4705         r_fb.water.texturewidth = waterwidth;
4706         r_fb.water.textureheight = waterheight;
4707         r_fb.water.camerawidth = waterwidth;
4708         r_fb.water.cameraheight = waterheight;
4709         r_fb.water.screenscale[0] = 0.5f;
4710         r_fb.water.screenscale[1] = 0.5f;
4711         r_fb.water.screencenter[0] = 0.5f;
4712         r_fb.water.screencenter[1] = 0.5f;
4713         r_fb.water.enabled = waterwidth != 0;
4714
4715         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
4716         r_fb.water.numwaterplanes = 0;
4717 }
4718
4719 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
4720 {
4721         int planeindex, bestplaneindex, vertexindex;
4722         vec3_t mins, maxs, normal, center, v, n;
4723         vec_t planescore, bestplanescore;
4724         mplane_t plane;
4725         r_waterstate_waterplane_t *p;
4726         texture_t *t = R_GetCurrentTexture(surface->texture);
4727
4728         rsurface.texture = t;
4729         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
4730         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
4731         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
4732                 return;
4733         // average the vertex normals, find the surface bounds (after deformvertexes)
4734         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
4735         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
4736         VectorCopy(n, normal);
4737         VectorCopy(v, mins);
4738         VectorCopy(v, maxs);
4739         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
4740         {
4741                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
4742                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
4743                 VectorAdd(normal, n, normal);
4744                 mins[0] = min(mins[0], v[0]);
4745                 mins[1] = min(mins[1], v[1]);
4746                 mins[2] = min(mins[2], v[2]);
4747                 maxs[0] = max(maxs[0], v[0]);
4748                 maxs[1] = max(maxs[1], v[1]);
4749                 maxs[2] = max(maxs[2], v[2]);
4750         }
4751         VectorNormalize(normal);
4752         VectorMAM(0.5f, mins, 0.5f, maxs, center);
4753
4754         VectorCopy(normal, plane.normal);
4755         VectorNormalize(plane.normal);
4756         plane.dist = DotProduct(center, plane.normal);
4757         PlaneClassify(&plane);
4758         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4759         {
4760                 // skip backfaces (except if nocullface is set)
4761 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4762 //                      return;
4763                 VectorNegate(plane.normal, plane.normal);
4764                 plane.dist *= -1;
4765                 PlaneClassify(&plane);
4766         }
4767
4768
4769         // find a matching plane if there is one
4770         bestplaneindex = -1;
4771         bestplanescore = 1048576.0f;
4772         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4773         {
4774                 if(p->camera_entity == t->camera_entity)
4775                 {
4776                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
4777                         if (bestplaneindex < 0 || bestplanescore > planescore)
4778                         {
4779                                 bestplaneindex = planeindex;
4780                                 bestplanescore = planescore;
4781                         }
4782                 }
4783         }
4784         planeindex = bestplaneindex;
4785
4786         // if this surface does not fit any known plane rendered this frame, add one
4787         if (planeindex < 0 || bestplanescore > 0.001f)
4788         {
4789                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
4790                 {
4791                         // store the new plane
4792                         planeindex = r_fb.water.numwaterplanes++;
4793                         p = r_fb.water.waterplanes + planeindex;
4794                         p->plane = plane;
4795                         // clear materialflags and pvs
4796                         p->materialflags = 0;
4797                         p->pvsvalid = false;
4798                         p->camera_entity = t->camera_entity;
4799                         VectorCopy(mins, p->mins);
4800                         VectorCopy(maxs, p->maxs);
4801                 }
4802                 else
4803                 {
4804                         // We're totally screwed.
4805                         return;
4806                 }
4807         }
4808         else
4809         {
4810                 // merge mins/maxs when we're adding this surface to the plane
4811                 p = r_fb.water.waterplanes + planeindex;
4812                 p->mins[0] = min(p->mins[0], mins[0]);
4813                 p->mins[1] = min(p->mins[1], mins[1]);
4814                 p->mins[2] = min(p->mins[2], mins[2]);
4815                 p->maxs[0] = max(p->maxs[0], maxs[0]);
4816                 p->maxs[1] = max(p->maxs[1], maxs[1]);
4817                 p->maxs[2] = max(p->maxs[2], maxs[2]);
4818         }
4819         // merge this surface's materialflags into the waterplane
4820         p->materialflags |= t->currentmaterialflags;
4821         if(!(p->materialflags & MATERIALFLAG_CAMERA))
4822         {
4823                 // merge this surface's PVS into the waterplane
4824                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4825                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4826                 {
4827                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4828                         p->pvsvalid = true;
4829                 }
4830         }
4831 }
4832
4833 extern cvar_t r_drawparticles;
4834 extern cvar_t r_drawdecals;
4835
4836 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
4837 {
4838         int myscissor[4];
4839         r_refdef_view_t originalview;
4840         r_refdef_view_t myview;
4841         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;
4842         r_waterstate_waterplane_t *p;
4843         vec3_t visorigin;
4844         r_rendertarget_t *rt;
4845
4846         originalview = r_refdef.view;
4847
4848         // lowquality hack, temporarily shut down some cvars and restore afterwards
4849         qualityreduction = r_water_lowquality.integer;
4850         if (qualityreduction > 0)
4851         {
4852                 if (qualityreduction >= 1)
4853                 {
4854                         old_r_shadows = r_shadows.integer;
4855                         old_r_worldrtlight = r_shadow_realtime_world.integer;
4856                         old_r_dlight = r_shadow_realtime_dlight.integer;
4857                         Cvar_SetValueQuick(&r_shadows, 0);
4858                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
4859                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
4860                 }
4861                 if (qualityreduction >= 2)
4862                 {
4863                         old_r_dynamic = r_dynamic.integer;
4864                         old_r_particles = r_drawparticles.integer;
4865                         old_r_decals = r_drawdecals.integer;
4866                         Cvar_SetValueQuick(&r_dynamic, 0);
4867                         Cvar_SetValueQuick(&r_drawparticles, 0);
4868                         Cvar_SetValueQuick(&r_drawdecals, 0);
4869                 }
4870         }
4871
4872         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
4873         {
4874                 p->rt_reflection = NULL;
4875                 p->rt_refraction = NULL;
4876                 p->rt_camera = NULL;
4877         }
4878
4879         // render views
4880         r_refdef.view = originalview;
4881         r_refdef.view.showdebug = false;
4882         r_refdef.view.width = r_fb.water.waterwidth;
4883         r_refdef.view.height = r_fb.water.waterheight;
4884         r_refdef.view.useclipplane = true;
4885         myview = r_refdef.view;
4886         r_fb.water.renderingscene = true;
4887         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4888         {
4889                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
4890                         continue;
4891
4892                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4893                 {
4894                         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);
4895                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4896                                 goto error;
4897                         r_refdef.view = myview;
4898                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4899                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4900                         if(r_water_scissormode.integer)
4901                         {
4902                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4903                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4904                                 {
4905                                         p->rt_reflection = NULL;
4906                                         p->rt_refraction = NULL;
4907                                         p->rt_camera = NULL;
4908                                         continue;
4909                                 }
4910                         }
4911
4912                         r_refdef.view.clipplane = p->plane;
4913                         // reflected view origin may be in solid, so don't cull with it
4914                         r_refdef.view.usevieworiginculling = false;
4915                         // reverse the cullface settings for this render
4916                         r_refdef.view.cullface_front = GL_FRONT;
4917                         r_refdef.view.cullface_back = GL_BACK;
4918                         // combined pvs (based on what can be seen from each surface center)
4919                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4920                         {
4921                                 r_refdef.view.usecustompvs = true;
4922                                 if (p->pvsvalid)
4923                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4924                                 else
4925                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4926                         }
4927
4928                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
4929                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4930                         GL_ScissorTest(false);
4931                         R_ClearScreen(r_refdef.fogenabled);
4932                         GL_ScissorTest(true);
4933                         if(r_water_scissormode.integer & 2)
4934                                 R_View_UpdateWithScissor(myscissor);
4935                         else
4936                                 R_View_Update();
4937                         R_AnimCache_CacheVisibleEntities();
4938                         if(r_water_scissormode.integer & 1)
4939                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4940                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4941
4942                         r_fb.water.hideplayer = false;
4943                         p->rt_reflection = rt;
4944                 }
4945
4946                 // render the normal view scene and copy into texture
4947                 // (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)
4948                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4949                 {
4950                         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);
4951                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4952                                 goto error;
4953                         r_refdef.view = myview;
4954                         if(r_water_scissormode.integer)
4955                         {
4956                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4957                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4958                                 {
4959                                         p->rt_reflection = NULL;
4960                                         p->rt_refraction = NULL;
4961                                         p->rt_camera = NULL;
4962                                         continue;
4963                                 }
4964                         }
4965
4966                         // combined pvs (based on what can be seen from each surface center)
4967                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4968                         {
4969                                 r_refdef.view.usecustompvs = true;
4970                                 if (p->pvsvalid)
4971                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4972                                 else
4973                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4974                         }
4975
4976                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
4977
4978                         r_refdef.view.clipplane = p->plane;
4979                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4980                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4981
4982                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
4983                         {
4984                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
4985                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
4986                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
4987                                 R_RenderView_UpdateViewVectors();
4988                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
4989                                 {
4990                                         r_refdef.view.usecustompvs = true;
4991                                         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);
4992                                 }
4993                         }
4994
4995                         PlaneClassify(&r_refdef.view.clipplane);
4996
4997                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4998                         GL_ScissorTest(false);
4999                         R_ClearScreen(r_refdef.fogenabled);
5000                         GL_ScissorTest(true);
5001                         if(r_water_scissormode.integer & 2)
5002                                 R_View_UpdateWithScissor(myscissor);
5003                         else
5004                                 R_View_Update();
5005                         R_AnimCache_CacheVisibleEntities();
5006                         if(r_water_scissormode.integer & 1)
5007                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5008                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5009
5010                         r_fb.water.hideplayer = false;
5011                         p->rt_refraction = rt;
5012                 }
5013                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5014                 {
5015                         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);
5016                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
5017                                 goto error;
5018                         r_refdef.view = myview;
5019
5020                         r_refdef.view.clipplane = p->plane;
5021                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5022                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5023
5024                         r_refdef.view.width = r_fb.water.camerawidth;
5025                         r_refdef.view.height = r_fb.water.cameraheight;
5026                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5027                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5028                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5029                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5030
5031                         if(p->camera_entity)
5032                         {
5033                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5034                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5035                         }
5036
5037                         // note: all of the view is used for displaying... so
5038                         // there is no use in scissoring
5039
5040                         // reverse the cullface settings for this render
5041                         r_refdef.view.cullface_front = GL_FRONT;
5042                         r_refdef.view.cullface_back = GL_BACK;
5043                         // also reverse the view matrix
5044                         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
5045                         R_RenderView_UpdateViewVectors();
5046                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5047                         {
5048                                 r_refdef.view.usecustompvs = true;
5049                                 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);
5050                         }
5051                         
5052                         // camera needs no clipplane
5053                         r_refdef.view.useclipplane = false;
5054                         // TODO: is the camera origin always valid?  if so we don't need to clear this
5055                         r_refdef.view.usevieworiginculling = false;
5056
5057                         PlaneClassify(&r_refdef.view.clipplane);
5058
5059                         r_fb.water.hideplayer = false;
5060
5061                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5062                         GL_ScissorTest(false);
5063                         R_ClearScreen(r_refdef.fogenabled);
5064                         GL_ScissorTest(true);
5065                         R_View_Update();
5066                         R_AnimCache_CacheVisibleEntities();
5067                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5068
5069                         r_fb.water.hideplayer = false;
5070                         p->rt_camera = rt;
5071                 }
5072
5073         }
5074         r_fb.water.renderingscene = false;
5075         r_refdef.view = originalview;
5076         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
5077         R_View_Update();
5078         R_AnimCache_CacheVisibleEntities();
5079         goto finish;
5080 error:
5081         r_refdef.view = originalview;
5082         r_fb.water.renderingscene = false;
5083         Cvar_SetValueQuick(&r_water, 0);
5084         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5085 finish:
5086         // lowquality hack, restore cvars
5087         if (qualityreduction > 0)
5088         {
5089                 if (qualityreduction >= 1)
5090                 {
5091                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5092                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5093                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5094                 }
5095                 if (qualityreduction >= 2)
5096                 {
5097                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5098                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5099                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5100                 }
5101         }
5102 }
5103
5104 static void R_Bloom_StartFrame(void)
5105 {
5106         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5107         int viewwidth, viewheight;
5108         textype_t textype = TEXTYPE_COLORBUFFER;
5109
5110         // clear the pointers to rendertargets from last frame as they're stale
5111         r_fb.rt_screen = NULL;
5112         r_fb.rt_bloom = NULL;
5113
5114         switch (vid.renderpath)
5115         {
5116         case RENDERPATH_GL32:
5117                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5118                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5119                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5120                 break;
5121         case RENDERPATH_GLES2:
5122                 r_fb.usedepthtextures = false;
5123                 break;
5124         }
5125
5126         if (r_viewscale_fpsscaling.integer)
5127         {
5128                 double actualframetime;
5129                 double targetframetime;
5130                 double adjust;
5131                 actualframetime = r_refdef.lastdrawscreentime;
5132                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5133                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5134                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5135                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5136                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5137                 viewscalefpsadjusted += adjust;
5138                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5139         }
5140         else
5141                 viewscalefpsadjusted = 1.0f;
5142
5143         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5144
5145         // set bloomwidth and bloomheight to the bloom resolution that will be
5146         // used (often less than the screen resolution for faster rendering)
5147         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
5148         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
5149         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
5150         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
5151         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
5152
5153         // calculate desired texture sizes
5154         screentexturewidth = viewwidth;
5155         screentextureheight = viewheight;
5156         bloomtexturewidth = r_fb.bloomwidth;
5157         bloomtextureheight = r_fb.bloomheight;
5158
5159         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))
5160         {
5161                 Cvar_SetValueQuick(&r_bloom, 0);
5162                 Cvar_SetValueQuick(&r_motionblur, 0);
5163                 Cvar_SetValueQuick(&r_damageblur, 0);
5164         }
5165
5166         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
5167         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
5168         {
5169                 if (r_fb.ghosttexture)
5170                         R_FreeTexture(r_fb.ghosttexture);
5171                 r_fb.ghosttexture = NULL;
5172
5173                 r_fb.screentexturewidth = screentexturewidth;
5174                 r_fb.screentextureheight = screentextureheight;
5175                 r_fb.textype = textype;
5176
5177                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
5178                 {
5179                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
5180                                 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);
5181                         r_fb.ghosttexture_valid = false;
5182                 }
5183         }
5184
5185         if (r_bloom.integer)
5186         {
5187                 // bloom texture is a different resolution
5188                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
5189                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5190                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
5191         }
5192         else
5193                 r_fb.bloomwidth = r_fb.bloomheight = 0;
5194
5195         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5196
5197         r_refdef.view.clear = true;
5198 }
5199
5200 static void R_Bloom_MakeTexture(void)
5201 {
5202         int x, range, dir;
5203         float xoffset, yoffset, r, brighten;
5204         float colorscale = r_bloom_colorscale.value;
5205         r_viewport_t bloomviewport;
5206         r_rendertarget_t *prev, *cur;
5207         textype_t textype = r_fb.rt_screen->colortextype[0];
5208
5209         r_refdef.stats[r_stat_bloom]++;
5210
5211         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5212
5213         // scale down screen texture to the bloom texture size
5214         CHECKGLERROR
5215         prev = r_fb.rt_screen;
5216         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5217         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5218         R_SetViewport(&bloomviewport);
5219         GL_CullFace(GL_NONE);
5220         GL_DepthTest(false);
5221         GL_BlendFunc(GL_ONE, GL_ZERO);
5222         GL_Color(colorscale, colorscale, colorscale, 1);
5223         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5224         // TODO: do boxfilter scale-down in shader?
5225         R_SetupShader_Generic(prev->colortexture[0], false, true, true);
5226         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5227         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5228         // we now have a properly scaled bloom image
5229
5230         // multiply bloom image by itself as many times as desired to darken it
5231         // TODO: if people actually use this it could be done more quickly in the previous shader pass
5232         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5233         {
5234                 prev = cur;
5235                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5236                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5237                 x *= 2;
5238                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
5239                 if(x <= 2)
5240                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
5241                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
5242                 GL_Color(1,1,1,1); // no fix factor supported here
5243                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5244                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5245                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5246                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5247         }
5248         CHECKGLERROR
5249
5250         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
5251         brighten = r_bloom_brighten.value;
5252         brighten = sqrt(brighten);
5253         if(range >= 1)
5254                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5255
5256         for (dir = 0;dir < 2;dir++)
5257         {
5258                 prev = cur;
5259                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5260                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5261                 // blend on at multiple vertical offsets to achieve a vertical blur
5262                 // TODO: do offset blends using GLSL
5263                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5264                 CHECKGLERROR
5265                 GL_BlendFunc(GL_ONE, GL_ZERO);
5266                 CHECKGLERROR
5267                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5268                 CHECKGLERROR
5269                 for (x = -range;x <= range;x++)
5270                 {
5271                         if (!dir){xoffset = 0;yoffset = x;}
5272                         else {xoffset = x;yoffset = 0;}
5273                         xoffset /= (float)prev->texturewidth;
5274                         yoffset /= (float)prev->textureheight;
5275                         // compute a texcoord array with the specified x and y offset
5276                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
5277                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
5278                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
5279                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
5280                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
5281                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
5282                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
5283                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
5284                         // this r value looks like a 'dot' particle, fading sharply to
5285                         // black at the edges
5286                         // (probably not realistic but looks good enough)
5287                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5288                         //r = brighten/(range*2+1);
5289                         r = brighten / (range * 2 + 1);
5290                         if(range >= 1)
5291                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
5292                         if (r <= 0)
5293                                 continue;
5294                         CHECKGLERROR
5295                         GL_Color(r, r, r, 1);
5296                         CHECKGLERROR
5297                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
5298                         CHECKGLERROR
5299                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5300                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5301                         CHECKGLERROR
5302                         GL_BlendFunc(GL_ONE, GL_ONE);
5303                         CHECKGLERROR
5304                 }
5305         }
5306
5307         // now we have the bloom image, so keep track of it
5308         r_fb.rt_bloom = cur;
5309 }
5310
5311 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5312 {
5313         dpuint64 permutation;
5314         float uservecs[4][4];
5315         rtexture_t *viewtexture;
5316         rtexture_t *bloomtexture;
5317
5318         R_EntityMatrix(&identitymatrix);
5319
5320         if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
5321         {
5322                 // declare variables
5323                 float blur_factor, blur_mouseaccel, blur_velocity;
5324                 static float blur_average; 
5325                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
5326
5327                 // set a goal for the factoring
5328                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
5329                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
5330                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
5331                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
5332                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
5333                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
5334
5335                 // from the goal, pick an averaged value between goal and last value
5336                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
5337                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
5338
5339                 // enforce minimum amount of blur 
5340                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
5341
5342                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
5343
5344                 // calculate values into a standard alpha
5345                 cl.motionbluralpha = 1 - exp(-
5346                                 (
5347                                         (r_motionblur.value * blur_factor / 80)
5348                                         +
5349                                         (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5350                                 )
5351                                 /
5352                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5353                                 );
5354
5355                 // randomization for the blur value to combat persistent ghosting
5356                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5357                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5358
5359                 // apply the blur
5360                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5361                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
5362                 {
5363                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5364                         GL_Color(1, 1, 1, cl.motionbluralpha);
5365                         R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
5366                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
5367                         R_SetupShader_Generic(r_fb.ghosttexture, false, true, true);
5368                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5369                         r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
5370                 }
5371
5372                 // updates old view angles for next pass
5373                 VectorCopy(cl.viewangles, blur_oldangles);
5374
5375                 // copy view into the ghost texture
5376                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
5377                 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
5378                 r_fb.ghosttexture_valid = true;
5379         }
5380
5381         if (r_fb.bloomwidth)
5382         {
5383                 // make the bloom texture
5384                 R_Bloom_MakeTexture();
5385         }
5386
5387 #if _MSC_VER >= 1400
5388 #define sscanf sscanf_s
5389 #endif
5390         memset(uservecs, 0, sizeof(uservecs));
5391         if (r_glsl_postprocess_uservec1_enable.integer)
5392                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5393         if (r_glsl_postprocess_uservec2_enable.integer)
5394                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5395         if (r_glsl_postprocess_uservec3_enable.integer)
5396                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5397         if (r_glsl_postprocess_uservec4_enable.integer)
5398                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5399
5400         // render to the screen fbo
5401         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5402         GL_Color(1, 1, 1, 1);
5403         GL_BlendFunc(GL_ONE, GL_ZERO);
5404
5405         viewtexture = r_fb.rt_screen->colortexture[0];
5406         bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
5407
5408         if (r_rendertarget_debug.integer >= 0)
5409         {
5410                 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
5411                 if (rt && rt->colortexture[0])
5412                 {
5413                         viewtexture = rt->colortexture[0];
5414                         bloomtexture = NULL;
5415                 }
5416         }
5417
5418         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
5419         switch(vid.renderpath)
5420         {
5421         case RENDERPATH_GL32:
5422         case RENDERPATH_GLES2:
5423                 permutation =
5424                         (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
5425                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5426                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
5427                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5428                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5429                 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5430                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
5431                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
5432                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
5433                 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]);
5434                 if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
5435                 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]);
5436                 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]);
5437                 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]);
5438                 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]);
5439                 if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5440                 if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5441                 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);
5442                 break;
5443         }
5444         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5445         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
5446 }
5447
5448 matrix4x4_t r_waterscrollmatrix;
5449
5450 void R_UpdateFog(void)
5451 {
5452         // Nehahra fog
5453         if (gamemode == GAME_NEHAHRA)
5454         {
5455                 if (gl_fogenable.integer)
5456                 {
5457                         r_refdef.oldgl_fogenable = true;
5458                         r_refdef.fog_density = gl_fogdensity.value;
5459                         r_refdef.fog_red = gl_fogred.value;
5460                         r_refdef.fog_green = gl_foggreen.value;
5461                         r_refdef.fog_blue = gl_fogblue.value;
5462                         r_refdef.fog_alpha = 1;
5463                         r_refdef.fog_start = 0;
5464                         r_refdef.fog_end = gl_skyclip.value;
5465                         r_refdef.fog_height = 1<<30;
5466                         r_refdef.fog_fadedepth = 128;
5467                 }
5468                 else if (r_refdef.oldgl_fogenable)
5469                 {
5470                         r_refdef.oldgl_fogenable = false;
5471                         r_refdef.fog_density = 0;
5472                         r_refdef.fog_red = 0;
5473                         r_refdef.fog_green = 0;
5474                         r_refdef.fog_blue = 0;
5475                         r_refdef.fog_alpha = 0;
5476                         r_refdef.fog_start = 0;
5477                         r_refdef.fog_end = 0;
5478                         r_refdef.fog_height = 1<<30;
5479                         r_refdef.fog_fadedepth = 128;
5480                 }
5481         }
5482
5483         // fog parms
5484         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5485         r_refdef.fog_start = max(0, r_refdef.fog_start);
5486         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5487
5488         if (r_refdef.fog_density && r_drawfog.integer)
5489         {
5490                 r_refdef.fogenabled = true;
5491                 // this is the point where the fog reaches 0.9986 alpha, which we
5492                 // consider a good enough cutoff point for the texture
5493                 // (0.9986 * 256 == 255.6)
5494                 if (r_fog_exp2.integer)
5495                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5496                 else
5497                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5498                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5499                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5500                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5501                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
5502                         R_BuildFogHeightTexture();
5503                 // fog color was already set
5504                 // update the fog texture
5505                 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)
5506                         R_BuildFogTexture();
5507                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
5508                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
5509         }
5510         else
5511                 r_refdef.fogenabled = false;
5512
5513         // fog color
5514         if (r_refdef.fog_density)
5515         {
5516                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5517                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5518                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5519
5520                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5521                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5522                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5523                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5524
5525                 {
5526                         vec3_t fogvec;
5527                         VectorCopy(r_refdef.fogcolor, fogvec);
5528                         //   color.rgb *= ContrastBoost * SceneBrightness;
5529                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5530                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5531                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5532                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5533                 }
5534         }
5535 }
5536
5537 void R_UpdateVariables(void)
5538 {
5539         R_Textures_Frame();
5540
5541         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
5542
5543         r_refdef.farclip = r_farclip_base.value;
5544         if (r_refdef.scene.worldmodel)
5545                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5546         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5547
5548         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5549                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5550         r_refdef.polygonfactor = 0;
5551         r_refdef.polygonoffset = 0;
5552
5553         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5554         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5555         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
5556         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5557         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5558         if (FAKELIGHT_ENABLED)
5559         {
5560                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
5561         }
5562         else if (r_refdef.scene.worldmodel)
5563         {
5564                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
5565         }
5566         if (r_showsurfaces.integer)
5567         {
5568                 r_refdef.scene.rtworld = false;
5569                 r_refdef.scene.rtworldshadows = false;
5570                 r_refdef.scene.rtdlight = false;
5571                 r_refdef.scene.rtdlightshadows = false;
5572                 r_refdef.scene.lightmapintensity = 0;
5573         }
5574
5575         r_gpuskeletal = false;
5576         switch(vid.renderpath)
5577         {
5578         case RENDERPATH_GL32:
5579                 r_gpuskeletal = r_glsl_skeletal.integer && !r_showsurfaces.integer;
5580         case RENDERPATH_GLES2:
5581                 if(!vid_gammatables_trivial)
5582                 {
5583                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5584                         {
5585                                 // build GLSL gamma texture
5586 #define RAMPWIDTH 256
5587                                 unsigned short ramp[RAMPWIDTH * 3];
5588                                 unsigned char rampbgr[RAMPWIDTH][4];
5589                                 int i;
5590
5591                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5592
5593                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5594                                 for(i = 0; i < RAMPWIDTH; ++i)
5595                                 {
5596                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5597                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5598                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5599                                         rampbgr[i][3] = 0;
5600                                 }
5601                                 if (r_texture_gammaramps)
5602                                 {
5603                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
5604                                 }
5605                                 else
5606                                 {
5607                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
5608                                 }
5609                         }
5610                 }
5611                 else
5612                 {
5613                         // remove GLSL gamma texture
5614                 }
5615                 break;
5616         }
5617 }
5618
5619 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5620 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5621 /*
5622 ================
5623 R_SelectScene
5624 ================
5625 */
5626 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5627         if( scenetype != r_currentscenetype ) {
5628                 // store the old scenetype
5629                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5630                 r_currentscenetype = scenetype;
5631                 // move in the new scene
5632                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5633         }
5634 }
5635
5636 /*
5637 ================
5638 R_GetScenePointer
5639 ================
5640 */
5641 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5642 {
5643         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5644         if( scenetype == r_currentscenetype ) {
5645                 return &r_refdef.scene;
5646         } else {
5647                 return &r_scenes_store[ scenetype ];
5648         }
5649 }
5650
5651 static int R_SortEntities_Compare(const void *ap, const void *bp)
5652 {
5653         const entity_render_t *a = *(const entity_render_t **)ap;
5654         const entity_render_t *b = *(const entity_render_t **)bp;
5655
5656         // 1. compare model
5657         if(a->model < b->model)
5658                 return -1;
5659         if(a->model > b->model)
5660                 return +1;
5661
5662         // 2. compare skin
5663         // TODO possibly calculate the REAL skinnum here first using
5664         // skinscenes?
5665         if(a->skinnum < b->skinnum)
5666                 return -1;
5667         if(a->skinnum > b->skinnum)
5668                 return +1;
5669
5670         // everything we compared is equal
5671         return 0;
5672 }
5673 static void R_SortEntities(void)
5674 {
5675         // below or equal 2 ents, sorting never gains anything
5676         if(r_refdef.scene.numentities <= 2)
5677                 return;
5678         // sort
5679         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
5680 }
5681
5682 /*
5683 ================
5684 R_RenderView
5685 ================
5686 */
5687 extern cvar_t r_shadow_bouncegrid;
5688 extern cvar_t v_isometric;
5689 extern void V_MakeViewIsometric(void);
5690 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
5691 {
5692         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
5693         int viewfbo = 0;
5694         rtexture_t *viewdepthtexture = NULL;
5695         rtexture_t *viewcolortexture = NULL;
5696         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
5697
5698         // finish any 2D rendering that was queued
5699         DrawQ_Finish();
5700
5701         if (r_timereport_active)
5702                 R_TimeReport("start");
5703         r_textureframe++; // used only by R_GetCurrentTexture
5704         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5705
5706         if(R_CompileShader_CheckStaticParms())
5707                 R_GLSL_Restart_f();
5708
5709         if (!r_drawentities.integer)
5710                 r_refdef.scene.numentities = 0;
5711         else if (r_sortentities.integer)
5712                 R_SortEntities();
5713
5714         R_AnimCache_ClearCache();
5715
5716         /* adjust for stereo display */
5717         if(R_Stereo_Active())
5718         {
5719                 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);
5720                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
5721         }
5722
5723         if (r_refdef.view.isoverlay)
5724         {
5725                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5726                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
5727                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
5728                 R_TimeReport("depthclear");
5729
5730                 r_refdef.view.showdebug = false;
5731
5732                 r_fb.water.enabled = false;
5733                 r_fb.water.numwaterplanes = 0;
5734
5735                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5736
5737                 r_refdef.view.matrix = originalmatrix;
5738
5739                 CHECKGLERROR
5740                 return;
5741         }
5742
5743         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
5744         {
5745                 r_refdef.view.matrix = originalmatrix;
5746                 return;
5747         }
5748
5749         r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
5750         if (v_isometric.integer && r_refdef.view.ismain)
5751                 V_MakeViewIsometric();
5752
5753         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
5754
5755         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
5756                 // in sRGB fallback, behave similar to true sRGB: convert this
5757                 // value from linear to sRGB
5758                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
5759
5760         R_RenderView_UpdateViewVectors();
5761
5762         R_Shadow_UpdateWorldLightSelection();
5763
5764         // this will set up r_fb.rt_screen
5765         R_Bloom_StartFrame();
5766
5767         // apply bloom brightness offset
5768         if(r_fb.rt_bloom)
5769                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
5770
5771         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
5772         if (r_fb.rt_screen)
5773         {
5774                 viewfbo = r_fb.rt_screen->fbo;
5775                 viewdepthtexture = r_fb.rt_screen->depthtexture;
5776                 viewcolortexture = r_fb.rt_screen->colortexture[0];
5777                 viewx = 0;
5778                 viewy = 0;
5779                 viewwidth = width;
5780                 viewheight = height;
5781         }
5782
5783         R_Water_StartFrame();
5784
5785         CHECKGLERROR
5786         if (r_timereport_active)
5787                 R_TimeReport("viewsetup");
5788
5789         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5790
5791         // clear the whole fbo every frame - otherwise the driver will consider
5792         // it to be an inter-frame texture and stall in multi-gpu configurations
5793         if (r_fb.rt_screen)
5794                 GL_ScissorTest(false);
5795         R_ClearScreen(r_refdef.fogenabled);
5796         if (r_timereport_active)
5797                 R_TimeReport("viewclear");
5798
5799         r_refdef.view.clear = true;
5800
5801         r_refdef.view.showdebug = true;
5802
5803         R_View_Update();
5804         if (r_timereport_active)
5805                 R_TimeReport("visibility");
5806
5807         R_AnimCache_CacheVisibleEntities();
5808         if (r_timereport_active)
5809                 R_TimeReport("animcache");
5810
5811         R_Shadow_UpdateBounceGridTexture();
5812         if (r_timereport_active && r_shadow_bouncegrid.integer)
5813                 R_TimeReport("bouncegrid");
5814
5815         r_fb.water.numwaterplanes = 0;
5816         if (r_fb.water.enabled)
5817                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5818
5819         // for the actual view render we use scissoring a fair amount, so scissor
5820         // test needs to be on
5821         if (r_fb.rt_screen)
5822                 GL_ScissorTest(true);
5823         GL_Scissor(viewx, viewy, viewwidth, viewheight);
5824         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5825         r_fb.water.numwaterplanes = 0;
5826
5827         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
5828         GL_ScissorTest(false);
5829
5830         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
5831         if (r_timereport_active)
5832                 R_TimeReport("blendview");
5833
5834         r_refdef.view.matrix = originalmatrix;
5835
5836         CHECKGLERROR
5837
5838         // go back to 2d rendering
5839         DrawQ_Start();
5840 }
5841
5842 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5843 {
5844         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5845         {
5846                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5847                 if (r_timereport_active)
5848                         R_TimeReport("waterworld");
5849         }
5850
5851         // don't let sound skip if going slow
5852         if (r_refdef.scene.extraupdate)
5853                 S_ExtraUpdate ();
5854
5855         R_DrawModelsAddWaterPlanes();
5856         if (r_timereport_active)
5857                 R_TimeReport("watermodels");
5858
5859         if (r_fb.water.numwaterplanes)
5860         {
5861                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5862                 if (r_timereport_active)
5863                         R_TimeReport("waterscenes");
5864         }
5865 }
5866
5867 extern cvar_t cl_locs_show;
5868 static void R_DrawLocs(void);
5869 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
5870 static void R_DrawModelDecals(void);
5871 extern cvar_t cl_decals_newsystem;
5872 extern qboolean r_shadow_usingdeferredprepass;
5873 extern int r_shadow_shadowmapatlas_modelshadows_size;
5874 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5875 {
5876         qboolean shadowmapping = false;
5877
5878         if (r_timereport_active)
5879                 R_TimeReport("beginscene");
5880
5881         r_refdef.stats[r_stat_renders]++;
5882
5883         R_UpdateFog();
5884
5885         // don't let sound skip if going slow
5886         if (r_refdef.scene.extraupdate)
5887                 S_ExtraUpdate ();
5888
5889         R_MeshQueue_BeginScene();
5890
5891         R_SkyStartFrame();
5892
5893         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);
5894
5895         if (r_timereport_active)
5896                 R_TimeReport("skystartframe");
5897
5898         if (cl.csqc_vidvars.drawworld)
5899         {
5900                 // don't let sound skip if going slow
5901                 if (r_refdef.scene.extraupdate)
5902                         S_ExtraUpdate ();
5903
5904                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5905                 {
5906                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5907                         if (r_timereport_active)
5908                                 R_TimeReport("worldsky");
5909                 }
5910
5911                 if (R_DrawBrushModelsSky() && r_timereport_active)
5912                         R_TimeReport("bmodelsky");
5913
5914                 if (skyrendermasked && skyrenderlater)
5915                 {
5916                         // we have to force off the water clipping plane while rendering sky
5917                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5918                         R_Sky();
5919                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5920                         if (r_timereport_active)
5921                                 R_TimeReport("sky");
5922                 }
5923         }
5924
5925         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
5926         r_shadow_viewfbo = viewfbo;
5927         r_shadow_viewdepthtexture = viewdepthtexture;
5928         r_shadow_viewcolortexture = viewcolortexture;
5929         r_shadow_viewx = viewx;
5930         r_shadow_viewy = viewy;
5931         r_shadow_viewwidth = viewwidth;
5932         r_shadow_viewheight = viewheight;
5933
5934         R_Shadow_PrepareModelShadows();
5935         R_Shadow_PrepareLights();
5936         if (r_timereport_active)
5937                 R_TimeReport("preparelights");
5938
5939         // render all the shadowmaps that will be used for this view
5940         shadowmapping = R_Shadow_ShadowMappingEnabled();
5941         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
5942         {
5943                 R_Shadow_DrawShadowMaps();
5944                 if (r_timereport_active)
5945                         R_TimeReport("shadowmaps");
5946         }
5947
5948         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
5949         if (r_shadow_usingdeferredprepass)
5950                 R_Shadow_DrawPrepass();
5951
5952         // now we begin the forward pass of the view render
5953         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5954         {
5955                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5956                 if (r_timereport_active)
5957                         R_TimeReport("worlddepth");
5958         }
5959         if (r_depthfirst.integer >= 2)
5960         {
5961                 R_DrawModelsDepth();
5962                 if (r_timereport_active)
5963                         R_TimeReport("modeldepth");
5964         }
5965
5966         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5967         {
5968                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5969                 if (r_timereport_active)
5970                         R_TimeReport("world");
5971         }
5972
5973         // don't let sound skip if going slow
5974         if (r_refdef.scene.extraupdate)
5975                 S_ExtraUpdate ();
5976
5977         R_DrawModels();
5978         if (r_timereport_active)
5979                 R_TimeReport("models");
5980
5981         // don't let sound skip if going slow
5982         if (r_refdef.scene.extraupdate)
5983                 S_ExtraUpdate ();
5984
5985         if (!r_shadow_usingdeferredprepass)
5986         {
5987                 R_Shadow_DrawLights();
5988                 if (r_timereport_active)
5989                         R_TimeReport("rtlights");
5990         }
5991
5992         // don't let sound skip if going slow
5993         if (r_refdef.scene.extraupdate)
5994                 S_ExtraUpdate ();
5995
5996         if (cl.csqc_vidvars.drawworld)
5997         {
5998                 if (cl_decals_newsystem.integer)
5999                 {
6000                         R_DrawModelDecals();
6001                         if (r_timereport_active)
6002                                 R_TimeReport("modeldecals");
6003                 }
6004                 else
6005                 {
6006                         R_DrawDecals();
6007                         if (r_timereport_active)
6008                                 R_TimeReport("decals");
6009                 }
6010
6011                 R_DrawParticles();
6012                 if (r_timereport_active)
6013                         R_TimeReport("particles");
6014
6015                 R_DrawExplosions();
6016                 if (r_timereport_active)
6017                         R_TimeReport("explosions");
6018         }
6019
6020         if (r_refdef.view.showdebug)
6021         {
6022                 if (cl_locs_show.integer)
6023                 {
6024                         R_DrawLocs();
6025                         if (r_timereport_active)
6026                                 R_TimeReport("showlocs");
6027                 }
6028
6029                 if (r_drawportals.integer)
6030                 {
6031                         R_DrawPortals();
6032                         if (r_timereport_active)
6033                                 R_TimeReport("portals");
6034                 }
6035
6036                 if (r_showbboxes_client.value > 0)
6037                 {
6038                         R_DrawEntityBBoxes(CLVM_prog);
6039                         if (r_timereport_active)
6040                                 R_TimeReport("clbboxes");
6041                 }
6042                 if (r_showbboxes.value > 0)
6043                 {
6044                         R_DrawEntityBBoxes(SVVM_prog);
6045                         if (r_timereport_active)
6046                                 R_TimeReport("svbboxes");
6047                 }
6048         }
6049
6050         if (r_transparent.integer)
6051         {
6052                 R_MeshQueue_RenderTransparent();
6053                 if (r_timereport_active)
6054                         R_TimeReport("drawtrans");
6055         }
6056
6057         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))
6058         {
6059                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6060                 if (r_timereport_active)
6061                         R_TimeReport("worlddebug");
6062                 R_DrawModelsDebug();
6063                 if (r_timereport_active)
6064                         R_TimeReport("modeldebug");
6065         }
6066
6067         if (cl.csqc_vidvars.drawworld)
6068         {
6069                 R_Shadow_DrawCoronas();
6070                 if (r_timereport_active)
6071                         R_TimeReport("coronas");
6072         }
6073
6074         // don't let sound skip if going slow
6075         if (r_refdef.scene.extraupdate)
6076                 S_ExtraUpdate ();
6077 }
6078
6079 static const unsigned short bboxelements[36] =
6080 {
6081         5, 1, 3, 5, 3, 7,
6082         6, 2, 0, 6, 0, 4,
6083         7, 3, 2, 7, 2, 6,
6084         4, 0, 1, 4, 1, 5,
6085         4, 5, 7, 4, 7, 6,
6086         1, 0, 2, 1, 2, 3,
6087 };
6088
6089 #define BBOXEDGES 13
6090 static const float bboxedges[BBOXEDGES][6] = 
6091 {
6092         // whole box
6093         { 0, 0, 0, 1, 1, 1 },
6094         // bottom edges
6095         { 0, 0, 0, 0, 1, 0 },
6096         { 0, 0, 0, 1, 0, 0 },
6097         { 0, 1, 0, 1, 1, 0 },
6098         { 1, 0, 0, 1, 1, 0 },
6099         // top edges
6100         { 0, 0, 1, 0, 1, 1 },
6101         { 0, 0, 1, 1, 0, 1 },
6102         { 0, 1, 1, 1, 1, 1 },
6103         { 1, 0, 1, 1, 1, 1 },
6104         // vertical edges
6105         { 0, 0, 0, 0, 0, 1 },
6106         { 1, 0, 0, 1, 0, 1 },
6107         { 0, 1, 0, 0, 1, 1 },
6108         { 1, 1, 0, 1, 1, 1 },
6109 };
6110
6111 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6112 {
6113         int numvertices = BBOXEDGES * 8;
6114         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
6115         int numtriangles = BBOXEDGES * 12;
6116         unsigned short elements[BBOXEDGES * 36];
6117         int i, edge;
6118         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
6119
6120         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
6121
6122         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6123         GL_DepthMask(false);
6124         GL_DepthRange(0, 1);
6125         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6126
6127         for (edge = 0; edge < BBOXEDGES; edge++)
6128         {
6129                 for (i = 0; i < 3; i++)
6130                 {
6131                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
6132                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
6133                 }
6134                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
6135                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
6136                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
6137                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
6138                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
6139                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
6140                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
6141                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
6142                 for (i = 0; i < 36; i++)
6143                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
6144         }
6145         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
6146         if (r_refdef.fogenabled)
6147         {
6148                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
6149                 {
6150                         f1 = RSurf_FogVertex(v);
6151                         f2 = 1 - f1;
6152                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6153                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6154                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6155                 }
6156         }
6157         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
6158         R_Mesh_ResetTextureState();
6159         R_SetupShader_Generic_NoTexture(false, false);
6160         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
6161 }
6162
6163 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6164 {
6165         // hacky overloading of the parameters
6166         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
6167         int i;
6168         float color[4];
6169         prvm_edict_t *edict;
6170
6171         GL_CullFace(GL_NONE);
6172         R_SetupShader_Generic_NoTexture(false, false);
6173
6174         for (i = 0;i < numsurfaces;i++)
6175         {
6176                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6177                 switch ((int)PRVM_serveredictfloat(edict, solid))
6178                 {
6179                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6180                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6181                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6182                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6183                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6184                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
6185                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6186                 }
6187                 if (prog == CLVM_prog)
6188                         color[3] *= r_showbboxes_client.value;
6189                 else
6190                         color[3] *= r_showbboxes.value;
6191                 color[3] = bound(0, color[3], 1);
6192                 GL_DepthTest(!r_showdisabledepthtest.integer);
6193                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6194         }
6195 }
6196
6197 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
6198 {
6199         int i;
6200         prvm_edict_t *edict;
6201         vec3_t center;
6202
6203         if (prog == NULL)
6204                 return;
6205
6206         for (i = 0; i < prog->num_edicts; i++)
6207         {
6208                 edict = PRVM_EDICT_NUM(i);
6209                 if (edict->priv.server->free)
6210                         continue;
6211                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6212                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
6213                         continue;
6214                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
6215                         continue;
6216                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6217                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
6218         }
6219 }
6220
6221 static const int nomodelelement3i[24] =
6222 {
6223         5, 2, 0,
6224         5, 1, 2,
6225         5, 0, 3,
6226         5, 3, 1,
6227         0, 2, 4,
6228         2, 1, 4,
6229         3, 0, 4,
6230         1, 3, 4
6231 };
6232
6233 static const unsigned short nomodelelement3s[24] =
6234 {
6235         5, 2, 0,
6236         5, 1, 2,
6237         5, 0, 3,
6238         5, 3, 1,
6239         0, 2, 4,
6240         2, 1, 4,
6241         3, 0, 4,
6242         1, 3, 4
6243 };
6244
6245 static const float nomodelvertex3f[6*3] =
6246 {
6247         -16,   0,   0,
6248          16,   0,   0,
6249           0, -16,   0,
6250           0,  16,   0,
6251           0,   0, -16,
6252           0,   0,  16
6253 };
6254
6255 static const float nomodelcolor4f[6*4] =
6256 {
6257         0.0f, 0.0f, 0.5f, 1.0f,
6258         0.0f, 0.0f, 0.5f, 1.0f,
6259         0.0f, 0.5f, 0.0f, 1.0f,
6260         0.0f, 0.5f, 0.0f, 1.0f,
6261         0.5f, 0.0f, 0.0f, 1.0f,
6262         0.5f, 0.0f, 0.0f, 1.0f
6263 };
6264
6265 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6266 {
6267         int i;
6268         float f1, f2, *c;
6269         float color4f[6*4];
6270
6271         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);
6272
6273         // this is only called once per entity so numsurfaces is always 1, and
6274         // surfacelist is always {0}, so this code does not handle batches
6275
6276         if (rsurface.ent_flags & RENDER_ADDITIVE)
6277         {
6278                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6279                 GL_DepthMask(false);
6280         }
6281         else if (ent->alpha < 1)
6282         {
6283                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6284                 GL_DepthMask(false);
6285         }
6286         else
6287         {
6288                 GL_BlendFunc(GL_ONE, GL_ZERO);
6289                 GL_DepthMask(true);
6290         }
6291         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6292         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6293         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6294         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6295         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6296         for (i = 0, c = color4f;i < 6;i++, c += 4)
6297         {
6298                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
6299                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
6300                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
6301                 c[3] *= ent->alpha;
6302         }
6303         if (r_refdef.fogenabled)
6304         {
6305                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6306                 {
6307                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6308                         f2 = 1 - f1;
6309                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6310                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6311                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6312                 }
6313         }
6314 //      R_Mesh_ResetTextureState();
6315         R_SetupShader_Generic_NoTexture(false, false);
6316         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6317         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6318 }
6319
6320 void R_DrawNoModel(entity_render_t *ent)
6321 {
6322         vec3_t org;
6323         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6324         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6325                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6326         else
6327                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6328 }
6329
6330 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
6331 {
6332         vec3_t right1, right2, diff, normal;
6333
6334         VectorSubtract (org2, org1, normal);
6335
6336         // calculate 'right' vector for start
6337         VectorSubtract (r_refdef.view.origin, org1, diff);
6338         CrossProduct (normal, diff, right1);
6339         VectorNormalize (right1);
6340
6341         // calculate 'right' vector for end
6342         VectorSubtract (r_refdef.view.origin, org2, diff);
6343         CrossProduct (normal, diff, right2);
6344         VectorNormalize (right2);
6345
6346         vert[ 0] = org1[0] + width * right1[0];
6347         vert[ 1] = org1[1] + width * right1[1];
6348         vert[ 2] = org1[2] + width * right1[2];
6349         vert[ 3] = org1[0] - width * right1[0];
6350         vert[ 4] = org1[1] - width * right1[1];
6351         vert[ 5] = org1[2] - width * right1[2];
6352         vert[ 6] = org2[0] - width * right2[0];
6353         vert[ 7] = org2[1] - width * right2[1];
6354         vert[ 8] = org2[2] - width * right2[2];
6355         vert[ 9] = org2[0] + width * right2[0];
6356         vert[10] = org2[1] + width * right2[1];
6357         vert[11] = org2[2] + width * right2[2];
6358 }
6359
6360 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)
6361 {
6362         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6363         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6364         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6365         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6366         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6367         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6368         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6369         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6370         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6371         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6372         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6373         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6374 }
6375
6376 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6377 {
6378         int i;
6379         float *vertex3f;
6380         float v[3];
6381         VectorSet(v, x, y, z);
6382         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6383                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6384                         break;
6385         if (i == mesh->numvertices)
6386         {
6387                 if (mesh->numvertices < mesh->maxvertices)
6388                 {
6389                         VectorCopy(v, vertex3f);
6390                         mesh->numvertices++;
6391                 }
6392                 return mesh->numvertices;
6393         }
6394         else
6395                 return i;
6396 }
6397
6398 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6399 {
6400         int i;
6401         int *e, element[3];
6402         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6403         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6404         e = mesh->element3i + mesh->numtriangles * 3;
6405         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6406         {
6407                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6408                 if (mesh->numtriangles < mesh->maxtriangles)
6409                 {
6410                         *e++ = element[0];
6411                         *e++ = element[1];
6412                         *e++ = element[2];
6413                         mesh->numtriangles++;
6414                 }
6415                 element[1] = element[2];
6416         }
6417 }
6418
6419 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6420 {
6421         int i;
6422         int *e, element[3];
6423         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6424         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6425         e = mesh->element3i + mesh->numtriangles * 3;
6426         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6427         {
6428                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6429                 if (mesh->numtriangles < mesh->maxtriangles)
6430                 {
6431                         *e++ = element[0];
6432                         *e++ = element[1];
6433                         *e++ = element[2];
6434                         mesh->numtriangles++;
6435                 }
6436                 element[1] = element[2];
6437         }
6438 }
6439
6440 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6441 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6442 {
6443         int planenum, planenum2;
6444         int w;
6445         int tempnumpoints;
6446         mplane_t *plane, *plane2;
6447         double maxdist;
6448         double temppoints[2][256*3];
6449         // figure out how large a bounding box we need to properly compute this brush
6450         maxdist = 0;
6451         for (w = 0;w < numplanes;w++)
6452                 maxdist = max(maxdist, fabs(planes[w].dist));
6453         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6454         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6455         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6456         {
6457                 w = 0;
6458                 tempnumpoints = 4;
6459                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6460                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6461                 {
6462                         if (planenum2 == planenum)
6463                                 continue;
6464                         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);
6465                         w = !w;
6466                 }
6467                 if (tempnumpoints < 3)
6468                         continue;
6469                 // generate elements forming a triangle fan for this polygon
6470                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6471         }
6472 }
6473
6474 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)
6475 {
6476         texturelayer_t *layer;
6477         layer = t->currentlayers + t->currentnumlayers++;
6478         layer->type = type;
6479         layer->depthmask = depthmask;
6480         layer->blendfunc1 = blendfunc1;
6481         layer->blendfunc2 = blendfunc2;
6482         layer->texture = texture;
6483         layer->texmatrix = *matrix;
6484         layer->color[0] = r;
6485         layer->color[1] = g;
6486         layer->color[2] = b;
6487         layer->color[3] = a;
6488 }
6489
6490 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
6491 {
6492         if(parms[0] == 0 && parms[1] == 0)
6493                 return false;
6494         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6495                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
6496                         return false;
6497         return true;
6498 }
6499
6500 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6501 {
6502         double index, f;
6503         index = parms[2] + rsurface.shadertime * parms[3];
6504         index -= floor(index);
6505         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
6506         {
6507         default:
6508         case Q3WAVEFUNC_NONE:
6509         case Q3WAVEFUNC_NOISE:
6510         case Q3WAVEFUNC_COUNT:
6511                 f = 0;
6512                 break;
6513         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6514         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6515         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6516         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6517         case Q3WAVEFUNC_TRIANGLE:
6518                 index *= 4;
6519                 f = index - floor(index);
6520                 if (index < 1)
6521                 {
6522                         // f = f;
6523                 }
6524                 else if (index < 2)
6525                         f = 1 - f;
6526                 else if (index < 3)
6527                         f = -f;
6528                 else
6529                         f = -(1 - f);
6530                 break;
6531         }
6532         f = parms[0] + parms[1] * f;
6533         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6534                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
6535         return (float) f;
6536 }
6537
6538 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6539 {
6540         int w, h, idx;
6541         float shadertime;
6542         float f;
6543         float offsetd[2];
6544         float tcmat[12];
6545         matrix4x4_t matrix, temp;
6546         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
6547         // it's better to have one huge fixup every 9 hours than gradual
6548         // degradation over time which looks consistently bad after many hours.
6549         //
6550         // tcmod scroll in particular suffers from this degradation which can't be
6551         // effectively worked around even with floor() tricks because we don't
6552         // know if tcmod scroll is the last tcmod being applied, and for clampmap
6553         // a workaround involving floor() would be incorrect anyway...
6554         shadertime = rsurface.shadertime;
6555         if (shadertime >= 32768.0f)
6556                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
6557         switch(tcmod->tcmod)
6558         {
6559                 case Q3TCMOD_COUNT:
6560                 case Q3TCMOD_NONE:
6561                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6562                                 matrix = r_waterscrollmatrix;
6563                         else
6564                                 matrix = identitymatrix;
6565                         break;
6566                 case Q3TCMOD_ENTITYTRANSLATE:
6567                         // this is used in Q3 to allow the gamecode to control texcoord
6568                         // scrolling on the entity, which is not supported in darkplaces yet.
6569                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6570                         break;
6571                 case Q3TCMOD_ROTATE:
6572                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6573                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
6574                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6575                         break;
6576                 case Q3TCMOD_SCALE:
6577                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6578                         break;
6579                 case Q3TCMOD_SCROLL:
6580                         // this particular tcmod is a "bug for bug" compatible one with regards to
6581                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
6582                         // specifically did the wrapping and so we must mimic that...
6583                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
6584                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
6585                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
6586                         break;
6587                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6588                         w = (int) tcmod->parms[0];
6589                         h = (int) tcmod->parms[1];
6590                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
6591                         f = f - floor(f);
6592                         idx = (int) floor(f * w * h);
6593                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6594                         break;
6595                 case Q3TCMOD_STRETCH:
6596                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6597                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6598                         break;
6599                 case Q3TCMOD_TRANSFORM:
6600                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6601                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6602                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6603                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6604                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6605                         break;
6606                 case Q3TCMOD_TURBULENT:
6607                         // this is handled in the RSurf_PrepareVertices function
6608                         matrix = identitymatrix;
6609                         break;
6610         }
6611         temp = *texmatrix;
6612         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6613 }
6614
6615 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6616 {
6617         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
6618         char name[MAX_QPATH];
6619         skinframe_t *skinframe;
6620         unsigned char pixels[296*194];
6621         strlcpy(cache->name, skinname, sizeof(cache->name));
6622         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6623         if (developer_loading.integer)
6624                 Con_Printf("loading %s\n", name);
6625         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6626         if (!skinframe || !skinframe->base)
6627         {
6628                 unsigned char *f;
6629                 fs_offset_t filesize;
6630                 skinframe = NULL;
6631                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6632                 if (f)
6633                 {
6634                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
6635                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6636                         Mem_Free(f);
6637                 }
6638         }
6639         cache->skinframe = skinframe;
6640 }
6641
6642 texture_t *R_GetCurrentTexture(texture_t *t)
6643 {
6644         int i, q;
6645         const entity_render_t *ent = rsurface.entity;
6646         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
6647         q3shaderinfo_layer_tcmod_t *tcmod;
6648         float specularscale = 0.0f;
6649
6650         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
6651                 return t->currentframe;
6652         t->update_lastrenderframe = r_textureframe;
6653         t->update_lastrenderentity = (void *)ent;
6654
6655         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
6656                 t->camera_entity = ent->entitynumber;
6657         else
6658                 t->camera_entity = 0;
6659
6660         // switch to an alternate material if this is a q1bsp animated material
6661         {
6662                 texture_t *texture = t;
6663                 int s = rsurface.ent_skinnum;
6664                 if ((unsigned int)s >= (unsigned int)model->numskins)
6665                         s = 0;
6666                 if (model->skinscenes)
6667                 {
6668                         if (model->skinscenes[s].framecount > 1)
6669                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6670                         else
6671                                 s = model->skinscenes[s].firstframe;
6672                 }
6673                 if (s > 0)
6674                         t = t + s * model->num_surfaces;
6675                 if (t->animated)
6676                 {
6677                         // use an alternate animation if the entity's frame is not 0,
6678                         // and only if the texture has an alternate animation
6679                         if (t->animated == 2) // q2bsp
6680                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
6681                         else if (rsurface.ent_alttextures && t->anim_total[1])
6682                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
6683                         else
6684                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
6685                 }
6686                 texture->currentframe = t;
6687         }
6688
6689         // update currentskinframe to be a qw skin or animation frame
6690         if (rsurface.ent_qwskin >= 0)
6691         {
6692                 i = rsurface.ent_qwskin;
6693                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6694                 {
6695                         r_qwskincache_size = cl.maxclients;
6696                         if (r_qwskincache)
6697                                 Mem_Free(r_qwskincache);
6698                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6699                 }
6700                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6701                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6702                 t->currentskinframe = r_qwskincache[i].skinframe;
6703                 if (t->materialshaderpass && t->currentskinframe == NULL)
6704                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6705         }
6706         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
6707                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6708         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
6709                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
6710
6711         t->currentmaterialflags = t->basematerialflags;
6712         t->currentalpha = rsurface.entity->alpha * t->basealpha;
6713         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_water.integer || r_novis.integer || r_trippy.integer))
6714                 t->currentalpha *= r_wateralpha.value;
6715         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
6716                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
6717         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
6718                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
6719
6720         // decide on which type of lighting to use for this surface
6721         if (rsurface.entity->render_modellight_forced)
6722                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6723         if (rsurface.entity->render_rtlight_disabled)
6724                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
6725         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
6726         {
6727                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
6728                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
6729                 for (q = 0; q < 3; q++)
6730                 {
6731                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
6732                         t->render_modellight_lightdir[q] = q == 2;
6733                         t->render_modellight_ambient[q] = 1;
6734                         t->render_modellight_diffuse[q] = 0;
6735                         t->render_modellight_specular[q] = 0;
6736                         t->render_lightmap_ambient[q] = 0;
6737                         t->render_lightmap_diffuse[q] = 0;
6738                         t->render_lightmap_specular[q] = 0;
6739                         t->render_rtlight_diffuse[q] = 0;
6740                         t->render_rtlight_specular[q] = 0;
6741                 }
6742         }
6743         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
6744         {
6745                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
6746                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
6747                 for (q = 0; q < 3; q++)
6748                 {
6749                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6750                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6751                         t->render_modellight_lightdir[q] = q == 2;
6752                         t->render_modellight_diffuse[q] = 0;
6753                         t->render_modellight_specular[q] = 0;
6754                         t->render_lightmap_ambient[q] = 0;
6755                         t->render_lightmap_diffuse[q] = 0;
6756                         t->render_lightmap_specular[q] = 0;
6757                         t->render_rtlight_diffuse[q] = 0;
6758                         t->render_rtlight_specular[q] = 0;
6759                 }
6760         }
6761         else if (FAKELIGHT_ENABLED)
6762         {
6763                 // no modellight if using fakelight for the map
6764                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
6765                 for (q = 0; q < 3; q++)
6766                 {
6767                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6768                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6769                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6770                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6771                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6772                         t->render_lightmap_ambient[q] = 0;
6773                         t->render_lightmap_diffuse[q] = 0;
6774                         t->render_lightmap_specular[q] = 0;
6775                         t->render_rtlight_diffuse[q] = 0;
6776                         t->render_rtlight_specular[q] = 0;
6777                 }
6778         }
6779         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
6780         {
6781                 // ambient + single direction light (modellight)
6782                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6783                 for (q = 0; q < 3; q++)
6784                 {
6785                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6786                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6787                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6788                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6789                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6790                         t->render_lightmap_ambient[q] = 0;
6791                         t->render_lightmap_diffuse[q] = 0;
6792                         t->render_lightmap_specular[q] = 0;
6793                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6794                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6795                 }
6796         }
6797         else
6798         {
6799                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
6800                 for (q = 0; q < 3; q++)
6801                 {
6802                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6803                         t->render_modellight_lightdir[q] = q == 2;
6804                         t->render_modellight_ambient[q] = 0;
6805                         t->render_modellight_diffuse[q] = 0;
6806                         t->render_modellight_specular[q] = 0;
6807                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
6808                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
6809                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
6810                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6811                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6812                 }
6813         }
6814
6815         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
6816         {
6817                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
6818                 // attribute, we punt it to the lightmap path and hope for the best,
6819                 // but lighting doesn't work.
6820                 //
6821                 // FIXME: this is fine for effects but CSQC polygons should be subject
6822                 // to lighting.
6823                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
6824                 for (q = 0; q < 3; q++)
6825                 {
6826                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6827                         t->render_modellight_lightdir[q] = q == 2;
6828                         t->render_modellight_ambient[q] = 0;
6829                         t->render_modellight_diffuse[q] = 0;
6830                         t->render_modellight_specular[q] = 0;
6831                         t->render_lightmap_ambient[q] = 0;
6832                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6833                         t->render_lightmap_specular[q] = 0;
6834                         t->render_rtlight_diffuse[q] = 0;
6835                         t->render_rtlight_specular[q] = 0;
6836                 }
6837         }
6838
6839         for (q = 0; q < 3; q++)
6840         {
6841                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
6842                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
6843         }
6844
6845         if (rsurface.ent_flags & RENDER_ADDITIVE)
6846                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6847         else if (t->currentalpha < 1)
6848                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6849         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
6850         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6851                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
6852         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6853                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6854         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6855                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6856         if (t->backgroundshaderpass)
6857                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6858         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6859         {
6860                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
6861                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6862         }
6863         else
6864                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
6865         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
6866         {
6867                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
6868                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
6869         }
6870         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6871                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6872
6873         // there is no tcmod
6874         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6875         {
6876                 t->currenttexmatrix = r_waterscrollmatrix;
6877                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6878         }
6879         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6880         {
6881                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6882                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6883         }
6884
6885         if (t->materialshaderpass)
6886                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6887                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6888
6889         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
6890         if (t->currentskinframe->qpixels)
6891                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6892         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6893         if (!t->basetexture)
6894                 t->basetexture = r_texture_notexture;
6895         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6896         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6897         t->nmaptexture = t->currentskinframe->nmap;
6898         if (!t->nmaptexture)
6899                 t->nmaptexture = r_texture_blanknormalmap;
6900         t->glosstexture = r_texture_black;
6901         t->glowtexture = t->currentskinframe->glow;
6902         t->fogtexture = t->currentskinframe->fog;
6903         t->reflectmasktexture = t->currentskinframe->reflect;
6904         if (t->backgroundshaderpass)
6905         {
6906                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
6907                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6908                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6909                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6910                 t->backgroundglosstexture = r_texture_black;
6911                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6912                 if (!t->backgroundnmaptexture)
6913                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6914                 // make sure that if glow is going to be used, both textures are not NULL
6915                 if (!t->backgroundglowtexture && t->glowtexture)
6916                         t->backgroundglowtexture = r_texture_black;
6917                 if (!t->glowtexture && t->backgroundglowtexture)
6918                         t->glowtexture = r_texture_black;
6919         }
6920         else
6921         {
6922                 t->backgroundbasetexture = r_texture_white;
6923                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6924                 t->backgroundglosstexture = r_texture_black;
6925                 t->backgroundglowtexture = NULL;
6926         }
6927         t->specularpower = r_shadow_glossexponent.value;
6928         // TODO: store reference values for these in the texture?
6929         if (r_shadow_gloss.integer > 0)
6930         {
6931                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6932                 {
6933                         if (r_shadow_glossintensity.value > 0)
6934                         {
6935                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6936                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6937                                 specularscale = r_shadow_glossintensity.value;
6938                         }
6939                 }
6940                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6941                 {
6942                         t->glosstexture = r_texture_white;
6943                         t->backgroundglosstexture = r_texture_white;
6944                         specularscale = r_shadow_gloss2intensity.value;
6945                         t->specularpower = r_shadow_gloss2exponent.value;
6946                 }
6947         }
6948         specularscale *= t->specularscalemod;
6949         t->specularpower *= t->specularpowermod;
6950
6951         // lightmaps mode looks bad with dlights using actual texturing, so turn
6952         // off the colormap and glossmap, but leave the normalmap on as it still
6953         // accurately represents the shading involved
6954         if (gl_lightmaps.integer)
6955         {
6956                 t->basetexture = r_texture_grey128;
6957                 t->pantstexture = r_texture_black;
6958                 t->shirttexture = r_texture_black;
6959                 if (gl_lightmaps.integer < 2)
6960                         t->nmaptexture = r_texture_blanknormalmap;
6961                 t->glosstexture = r_texture_black;
6962                 t->glowtexture = NULL;
6963                 t->fogtexture = NULL;
6964                 t->reflectmasktexture = NULL;
6965                 t->backgroundbasetexture = NULL;
6966                 if (gl_lightmaps.integer < 2)
6967                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6968                 t->backgroundglosstexture = r_texture_black;
6969                 t->backgroundglowtexture = NULL;
6970                 specularscale = 0;
6971                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6972         }
6973
6974         if (specularscale != 1.0f)
6975         {
6976                 for (q = 0; q < 3; q++)
6977                 {
6978                         t->render_modellight_specular[q] *= specularscale;
6979                         t->render_lightmap_specular[q] *= specularscale;
6980                         t->render_rtlight_specular[q] *= specularscale;
6981                 }
6982         }
6983
6984         t->currentnumlayers = 0;
6985         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6986         {
6987                 int blendfunc1, blendfunc2;
6988                 qboolean depthmask;
6989                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6990                 {
6991                         blendfunc1 = GL_SRC_ALPHA;
6992                         blendfunc2 = GL_ONE;
6993                 }
6994                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6995                 {
6996                         blendfunc1 = GL_SRC_ALPHA;
6997                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6998                 }
6999                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7000                 {
7001                         blendfunc1 = t->customblendfunc[0];
7002                         blendfunc2 = t->customblendfunc[1];
7003                 }
7004                 else
7005                 {
7006                         blendfunc1 = GL_ONE;
7007                         blendfunc2 = GL_ZERO;
7008                 }
7009                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7010                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7011                 {
7012                         // basic lit geometry
7013                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
7014                         // add pants/shirt if needed
7015                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7016                                 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);
7017                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7018                                 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);
7019                 }
7020                 else
7021                 {
7022                         // basic lit geometry
7023                         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);
7024                         // add pants/shirt if needed
7025                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7026                                 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);
7027                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7028                                 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);
7029                         // now add ambient passes if needed
7030                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
7031                         {
7032                                 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);
7033                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
7034                                         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);
7035                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
7036                                         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);
7037                         }
7038                 }
7039                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7040                         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);
7041                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7042                 {
7043                         // if this is opaque use alpha blend which will darken the earlier
7044                         // passes cheaply.
7045                         //
7046                         // if this is an alpha blended material, all the earlier passes
7047                         // were darkened by fog already, so we only need to add the fog
7048                         // color ontop through the fog mask texture
7049                         //
7050                         // if this is an additive blended material, all the earlier passes
7051                         // were darkened by fog already, and we should not add fog color
7052                         // (because the background was not darkened, there is no fog color
7053                         // that was lost behind it).
7054                         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);
7055                 }
7056         }
7057
7058         return t;
7059 }
7060
7061 rsurfacestate_t rsurface;
7062
7063 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7064 {
7065         dp_model_t *model = ent->model;
7066         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7067         //      return;
7068         rsurface.entity = (entity_render_t *)ent;
7069         rsurface.skeleton = ent->skeleton;
7070         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7071         rsurface.ent_skinnum = ent->skinnum;
7072         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;
7073         rsurface.ent_flags = ent->flags;
7074         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
7075                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
7076         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7077         rsurface.matrix = ent->matrix;
7078         rsurface.inversematrix = ent->inversematrix;
7079         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7080         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7081         R_EntityMatrix(&rsurface.matrix);
7082         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7083         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7084         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
7085         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7086         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7087         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7088         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7089         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7090         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7091         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7092         if (ent->model->brush.submodel && !prepass)
7093         {
7094                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7095                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7096         }
7097         // if the animcache code decided it should use the shader path, skip the deform step
7098         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
7099         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
7100         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
7101         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
7102         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
7103         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
7104         {
7105                 if (ent->animcache_vertex3f)
7106                 {
7107                         r_refdef.stats[r_stat_batch_entitycache_count]++;
7108                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
7109                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
7110                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
7111                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7112                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
7113                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
7114                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7115                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
7116                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
7117                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7118                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
7119                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
7120                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7121                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
7122                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
7123                 }
7124                 else if (wanttangents)
7125                 {
7126                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7127                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7128                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7129                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7130                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7131                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7132                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7133                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7134                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7135                         rsurface.modelvertex3f_vertexbuffer = NULL;
7136                         rsurface.modelvertex3f_bufferoffset = 0;
7137                         rsurface.modelvertex3f_vertexbuffer = 0;
7138                         rsurface.modelvertex3f_bufferoffset = 0;
7139                         rsurface.modelsvector3f_vertexbuffer = 0;
7140                         rsurface.modelsvector3f_bufferoffset = 0;
7141                         rsurface.modeltvector3f_vertexbuffer = 0;
7142                         rsurface.modeltvector3f_bufferoffset = 0;
7143                         rsurface.modelnormal3f_vertexbuffer = 0;
7144                         rsurface.modelnormal3f_bufferoffset = 0;
7145                 }
7146                 else if (wantnormals)
7147                 {
7148                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7149                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7150                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7151                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7152                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7153                         rsurface.modelsvector3f = NULL;
7154                         rsurface.modeltvector3f = NULL;
7155                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7156                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7157                         rsurface.modelvertex3f_vertexbuffer = NULL;
7158                         rsurface.modelvertex3f_bufferoffset = 0;
7159                         rsurface.modelvertex3f_vertexbuffer = 0;
7160                         rsurface.modelvertex3f_bufferoffset = 0;
7161                         rsurface.modelsvector3f_vertexbuffer = 0;
7162                         rsurface.modelsvector3f_bufferoffset = 0;
7163                         rsurface.modeltvector3f_vertexbuffer = 0;
7164                         rsurface.modeltvector3f_bufferoffset = 0;
7165                         rsurface.modelnormal3f_vertexbuffer = 0;
7166                         rsurface.modelnormal3f_bufferoffset = 0;
7167                 }
7168                 else
7169                 {
7170                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7171                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7172                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7173                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7174                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7175                         rsurface.modelsvector3f = NULL;
7176                         rsurface.modeltvector3f = NULL;
7177                         rsurface.modelnormal3f = NULL;
7178                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7179                         rsurface.modelvertex3f_vertexbuffer = NULL;
7180                         rsurface.modelvertex3f_bufferoffset = 0;
7181                         rsurface.modelvertex3f_vertexbuffer = 0;
7182                         rsurface.modelvertex3f_bufferoffset = 0;
7183                         rsurface.modelsvector3f_vertexbuffer = 0;
7184                         rsurface.modelsvector3f_bufferoffset = 0;
7185                         rsurface.modeltvector3f_vertexbuffer = 0;
7186                         rsurface.modeltvector3f_bufferoffset = 0;
7187                         rsurface.modelnormal3f_vertexbuffer = 0;
7188                         rsurface.modelnormal3f_bufferoffset = 0;
7189                 }
7190                 rsurface.modelgeneratedvertex = true;
7191         }
7192         else
7193         {
7194                 if (rsurface.entityskeletaltransform3x4)
7195                 {
7196                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
7197                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
7198                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
7199                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
7200                 }
7201                 else
7202                 {
7203                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
7204                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
7205                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
7206                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
7207                 }
7208                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7209                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7210                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7211                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7212                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7213                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7214                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7215                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7216                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7217                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7218                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7219                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7220                 rsurface.modelgeneratedvertex = false;
7221         }
7222         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7223         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7224         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7225         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7226         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7227         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7228         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7229         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7230         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7231         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
7232         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7233         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
7234         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
7235         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7236         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
7237         rsurface.modelelement3i = model->surfmesh.data_element3i;
7238         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7239         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7240         rsurface.modelelement3s = model->surfmesh.data_element3s;
7241         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7242         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7243         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7244         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7245         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7246         rsurface.modelsurfaces = model->data_surfaces;
7247         rsurface.batchgeneratedvertex = false;
7248         rsurface.batchfirstvertex = 0;
7249         rsurface.batchnumvertices = 0;
7250         rsurface.batchfirsttriangle = 0;
7251         rsurface.batchnumtriangles = 0;
7252         rsurface.batchvertex3f  = NULL;
7253         rsurface.batchvertex3f_vertexbuffer = NULL;
7254         rsurface.batchvertex3f_bufferoffset = 0;
7255         rsurface.batchsvector3f = NULL;
7256         rsurface.batchsvector3f_vertexbuffer = NULL;
7257         rsurface.batchsvector3f_bufferoffset = 0;
7258         rsurface.batchtvector3f = NULL;
7259         rsurface.batchtvector3f_vertexbuffer = NULL;
7260         rsurface.batchtvector3f_bufferoffset = 0;
7261         rsurface.batchnormal3f  = NULL;
7262         rsurface.batchnormal3f_vertexbuffer = NULL;
7263         rsurface.batchnormal3f_bufferoffset = 0;
7264         rsurface.batchlightmapcolor4f = NULL;
7265         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7266         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7267         rsurface.batchtexcoordtexture2f = NULL;
7268         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7269         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7270         rsurface.batchtexcoordlightmap2f = NULL;
7271         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7272         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7273         rsurface.batchskeletalindex4ub = NULL;
7274         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7275         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7276         rsurface.batchskeletalweight4ub = NULL;
7277         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7278         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7279         rsurface.batchelement3i = NULL;
7280         rsurface.batchelement3i_indexbuffer = NULL;
7281         rsurface.batchelement3i_bufferoffset = 0;
7282         rsurface.batchelement3s = NULL;
7283         rsurface.batchelement3s_indexbuffer = NULL;
7284         rsurface.batchelement3s_bufferoffset = 0;
7285         rsurface.forcecurrenttextureupdate = false;
7286 }
7287
7288 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)
7289 {
7290         rsurface.entity = r_refdef.scene.worldentity;
7291         rsurface.skeleton = NULL;
7292         rsurface.ent_skinnum = 0;
7293         rsurface.ent_qwskin = -1;
7294         rsurface.ent_flags = entflags;
7295         rsurface.shadertime = r_refdef.scene.time - shadertime;
7296         rsurface.modelnumvertices = numvertices;
7297         rsurface.modelnumtriangles = numtriangles;
7298         rsurface.matrix = *matrix;
7299         rsurface.inversematrix = *inversematrix;
7300         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7301         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7302         R_EntityMatrix(&rsurface.matrix);
7303         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7304         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7305         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7306         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7307         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7308         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7309         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7310         rsurface.frameblend[0].lerp = 1;
7311         rsurface.ent_alttextures = false;
7312         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7313         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7314         rsurface.entityskeletaltransform3x4 = NULL;
7315         rsurface.entityskeletaltransform3x4buffer = NULL;
7316         rsurface.entityskeletaltransform3x4offset = 0;
7317         rsurface.entityskeletaltransform3x4size = 0;
7318         rsurface.entityskeletalnumtransforms = 0;
7319         r_refdef.stats[r_stat_batch_entitycustom_count]++;
7320         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
7321         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
7322         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
7323         if (wanttangents)
7324         {
7325                 rsurface.modelvertex3f = (float *)vertex3f;
7326                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7327                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7328                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7329         }
7330         else if (wantnormals)
7331         {
7332                 rsurface.modelvertex3f = (float *)vertex3f;
7333                 rsurface.modelsvector3f = NULL;
7334                 rsurface.modeltvector3f = NULL;
7335                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7336         }
7337         else
7338         {
7339                 rsurface.modelvertex3f = (float *)vertex3f;
7340                 rsurface.modelsvector3f = NULL;
7341                 rsurface.modeltvector3f = NULL;
7342                 rsurface.modelnormal3f = NULL;
7343         }
7344         rsurface.modelvertex3f_vertexbuffer = 0;
7345         rsurface.modelvertex3f_bufferoffset = 0;
7346         rsurface.modelsvector3f_vertexbuffer = 0;
7347         rsurface.modelsvector3f_bufferoffset = 0;
7348         rsurface.modeltvector3f_vertexbuffer = 0;
7349         rsurface.modeltvector3f_bufferoffset = 0;
7350         rsurface.modelnormal3f_vertexbuffer = 0;
7351         rsurface.modelnormal3f_bufferoffset = 0;
7352         rsurface.modelgeneratedvertex = true;
7353         rsurface.modellightmapcolor4f  = (float *)color4f;
7354         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7355         rsurface.modellightmapcolor4f_bufferoffset = 0;
7356         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7357         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7358         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7359         rsurface.modeltexcoordlightmap2f  = NULL;
7360         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7361         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7362         rsurface.modelskeletalindex4ub = NULL;
7363         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
7364         rsurface.modelskeletalindex4ub_bufferoffset = 0;
7365         rsurface.modelskeletalweight4ub = NULL;
7366         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
7367         rsurface.modelskeletalweight4ub_bufferoffset = 0;
7368         rsurface.modelelement3i = (int *)element3i;
7369         rsurface.modelelement3i_indexbuffer = NULL;
7370         rsurface.modelelement3i_bufferoffset = 0;
7371         rsurface.modelelement3s = (unsigned short *)element3s;
7372         rsurface.modelelement3s_indexbuffer = NULL;
7373         rsurface.modelelement3s_bufferoffset = 0;
7374         rsurface.modellightmapoffsets = NULL;
7375         rsurface.modelsurfaces = NULL;
7376         rsurface.batchgeneratedvertex = false;
7377         rsurface.batchfirstvertex = 0;
7378         rsurface.batchnumvertices = 0;
7379         rsurface.batchfirsttriangle = 0;
7380         rsurface.batchnumtriangles = 0;
7381         rsurface.batchvertex3f  = NULL;
7382         rsurface.batchvertex3f_vertexbuffer = NULL;
7383         rsurface.batchvertex3f_bufferoffset = 0;
7384         rsurface.batchsvector3f = NULL;
7385         rsurface.batchsvector3f_vertexbuffer = NULL;
7386         rsurface.batchsvector3f_bufferoffset = 0;
7387         rsurface.batchtvector3f = NULL;
7388         rsurface.batchtvector3f_vertexbuffer = NULL;
7389         rsurface.batchtvector3f_bufferoffset = 0;
7390         rsurface.batchnormal3f  = NULL;
7391         rsurface.batchnormal3f_vertexbuffer = NULL;
7392         rsurface.batchnormal3f_bufferoffset = 0;
7393         rsurface.batchlightmapcolor4f = NULL;
7394         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7395         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7396         rsurface.batchtexcoordtexture2f = NULL;
7397         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7398         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7399         rsurface.batchtexcoordlightmap2f = NULL;
7400         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7401         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7402         rsurface.batchskeletalindex4ub = NULL;
7403         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7404         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7405         rsurface.batchskeletalweight4ub = NULL;
7406         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7407         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7408         rsurface.batchelement3i = NULL;
7409         rsurface.batchelement3i_indexbuffer = NULL;
7410         rsurface.batchelement3i_bufferoffset = 0;
7411         rsurface.batchelement3s = NULL;
7412         rsurface.batchelement3s_indexbuffer = NULL;
7413         rsurface.batchelement3s_bufferoffset = 0;
7414         rsurface.forcecurrenttextureupdate = true;
7415
7416         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7417         {
7418                 if ((wantnormals || wanttangents) && !normal3f)
7419                 {
7420                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7421                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7422                 }
7423                 if (wanttangents && !svector3f)
7424                 {
7425                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7426                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7427                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7428                 }
7429         }
7430 }
7431
7432 float RSurf_FogPoint(const float *v)
7433 {
7434         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7435         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7436         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7437         float FogHeightFade = r_refdef.fogheightfade;
7438         float fogfrac;
7439         unsigned int fogmasktableindex;
7440         if (r_refdef.fogplaneviewabove)
7441                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7442         else
7443                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7444         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7445         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7446 }
7447
7448 float RSurf_FogVertex(const float *v)
7449 {
7450         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7451         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7452         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7453         float FogHeightFade = rsurface.fogheightfade;
7454         float fogfrac;
7455         unsigned int fogmasktableindex;
7456         if (r_refdef.fogplaneviewabove)
7457                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7458         else
7459                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7460         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7461         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7462 }
7463
7464 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7465 {
7466         int i;
7467         for (i = 0;i < numelements;i++)
7468                 outelement3i[i] = inelement3i[i] + adjust;
7469 }
7470
7471 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7472 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7473 {
7474         int deformindex;
7475         int firsttriangle;
7476         int numtriangles;
7477         int firstvertex;
7478         int endvertex;
7479         int numvertices;
7480         int surfacefirsttriangle;
7481         int surfacenumtriangles;
7482         int surfacefirstvertex;
7483         int surfaceendvertex;
7484         int surfacenumvertices;
7485         int batchnumsurfaces = texturenumsurfaces;
7486         int batchnumvertices;
7487         int batchnumtriangles;
7488         int i, j;
7489         qboolean gaps;
7490         qboolean dynamicvertex;
7491         float amplitude;
7492         float animpos;
7493         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7494         float waveparms[4];
7495         unsigned char *ub;
7496         q3shaderinfo_deform_t *deform;
7497         const msurface_t *surface, *firstsurface;
7498         if (!texturenumsurfaces)
7499                 return;
7500         // find vertex range of this surface batch
7501         gaps = false;
7502         firstsurface = texturesurfacelist[0];
7503         firsttriangle = firstsurface->num_firsttriangle;
7504         batchnumvertices = 0;
7505         batchnumtriangles = 0;
7506         firstvertex = endvertex = firstsurface->num_firstvertex;
7507         for (i = 0;i < texturenumsurfaces;i++)
7508         {
7509                 surface = texturesurfacelist[i];
7510                 if (surface != firstsurface + i)
7511                         gaps = true;
7512                 surfacefirstvertex = surface->num_firstvertex;
7513                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
7514                 surfacenumvertices = surface->num_vertices;
7515                 surfacenumtriangles = surface->num_triangles;
7516                 if (firstvertex > surfacefirstvertex)
7517                         firstvertex = surfacefirstvertex;
7518                 if (endvertex < surfaceendvertex)
7519                         endvertex = surfaceendvertex;
7520                 batchnumvertices += surfacenumvertices;
7521                 batchnumtriangles += surfacenumtriangles;
7522         }
7523
7524         r_refdef.stats[r_stat_batch_batches]++;
7525         if (gaps)
7526                 r_refdef.stats[r_stat_batch_withgaps]++;
7527         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
7528         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
7529         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
7530
7531         // we now know the vertex range used, and if there are any gaps in it
7532         rsurface.batchfirstvertex = firstvertex;
7533         rsurface.batchnumvertices = endvertex - firstvertex;
7534         rsurface.batchfirsttriangle = firsttriangle;
7535         rsurface.batchnumtriangles = batchnumtriangles;
7536
7537         // check if any dynamic vertex processing must occur
7538         dynamicvertex = false;
7539
7540         // a cvar to force the dynamic vertex path to be taken, for debugging
7541         if (r_batch_debugdynamicvertexpath.integer)
7542         {
7543                 if (!dynamicvertex)
7544                 {
7545                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
7546                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
7547                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
7548                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
7549                 }
7550                 dynamicvertex = true;
7551         }
7552
7553         // if there is a chance of animated vertex colors, it's a dynamic batch
7554         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
7555         {
7556                 if (!dynamicvertex)
7557                 {
7558                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
7559                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
7560                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
7561                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
7562                 }
7563                 dynamicvertex = true;
7564         }
7565
7566         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
7567         {
7568                 switch (deform->deform)
7569                 {
7570                 default:
7571                 case Q3DEFORM_PROJECTIONSHADOW:
7572                 case Q3DEFORM_TEXT0:
7573                 case Q3DEFORM_TEXT1:
7574                 case Q3DEFORM_TEXT2:
7575                 case Q3DEFORM_TEXT3:
7576                 case Q3DEFORM_TEXT4:
7577                 case Q3DEFORM_TEXT5:
7578                 case Q3DEFORM_TEXT6:
7579                 case Q3DEFORM_TEXT7:
7580                 case Q3DEFORM_NONE:
7581                         break;
7582                 case Q3DEFORM_AUTOSPRITE:
7583                         if (!dynamicvertex)
7584                         {
7585                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
7586                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
7587                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
7588                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
7589                         }
7590                         dynamicvertex = true;
7591                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
7592                         break;
7593                 case Q3DEFORM_AUTOSPRITE2:
7594                         if (!dynamicvertex)
7595                         {
7596                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
7597                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
7598                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
7599                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
7600                         }
7601                         dynamicvertex = true;
7602                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7603                         break;
7604                 case Q3DEFORM_NORMAL:
7605                         if (!dynamicvertex)
7606                         {
7607                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
7608                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
7609                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
7610                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
7611                         }
7612                         dynamicvertex = true;
7613                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7614                         break;
7615                 case Q3DEFORM_WAVE:
7616                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7617                                 break; // if wavefunc is a nop, ignore this transform
7618                         if (!dynamicvertex)
7619                         {
7620                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
7621                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
7622                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
7623                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
7624                         }
7625                         dynamicvertex = true;
7626                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7627                         break;
7628                 case Q3DEFORM_BULGE:
7629                         if (!dynamicvertex)
7630                         {
7631                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
7632                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
7633                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
7634                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
7635                         }
7636                         dynamicvertex = true;
7637                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7638                         break;
7639                 case Q3DEFORM_MOVE:
7640                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7641                                 break; // if wavefunc is a nop, ignore this transform
7642                         if (!dynamicvertex)
7643                         {
7644                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
7645                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
7646                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
7647                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
7648                         }
7649                         dynamicvertex = true;
7650                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7651                         break;
7652                 }
7653         }
7654         if (rsurface.texture->materialshaderpass)
7655         {
7656                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
7657                 {
7658                 default:
7659                 case Q3TCGEN_TEXTURE:
7660                         break;
7661                 case Q3TCGEN_LIGHTMAP:
7662                         if (!dynamicvertex)
7663                         {
7664                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
7665                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
7666                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
7667                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
7668                         }
7669                         dynamicvertex = true;
7670                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
7671                         break;
7672                 case Q3TCGEN_VECTOR:
7673                         if (!dynamicvertex)
7674                         {
7675                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
7676                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
7677                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
7678                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
7679                         }
7680                         dynamicvertex = true;
7681                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7682                         break;
7683                 case Q3TCGEN_ENVIRONMENT:
7684                         if (!dynamicvertex)
7685                         {
7686                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
7687                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
7688                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
7689                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
7690                         }
7691                         dynamicvertex = true;
7692                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
7693                         break;
7694                 }
7695                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7696                 {
7697                         if (!dynamicvertex)
7698                         {
7699                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
7700                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
7701                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
7702                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
7703                         }
7704                         dynamicvertex = true;
7705                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7706                 }
7707         }
7708
7709         // the caller can specify BATCHNEED_NOGAPS to force a batch with
7710         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
7711         // we ensure this by treating the vertex batch as dynamic...
7712         if ((batchneed & BATCHNEED_ALWAYSCOPY) || ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0)))
7713         {
7714                 if (!dynamicvertex)
7715                 {
7716                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
7717                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
7718                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
7719                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
7720                 }
7721                 dynamicvertex = true;
7722         }
7723
7724         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
7725         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
7726                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
7727
7728         rsurface.batchvertex3f = rsurface.modelvertex3f;
7729         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
7730         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7731         rsurface.batchsvector3f = rsurface.modelsvector3f;
7732         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
7733         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7734         rsurface.batchtvector3f = rsurface.modeltvector3f;
7735         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
7736         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7737         rsurface.batchnormal3f = rsurface.modelnormal3f;
7738         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
7739         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7740         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
7741         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
7742         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
7743         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
7744         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
7745         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7746         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7747         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
7748         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7749         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
7750         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
7751         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
7752         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
7753         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
7754         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
7755         rsurface.batchelement3i = rsurface.modelelement3i;
7756         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
7757         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
7758         rsurface.batchelement3s = rsurface.modelelement3s;
7759         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
7760         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
7761         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
7762         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
7763         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
7764         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
7765         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
7766
7767         // if any dynamic vertex processing has to occur in software, we copy the
7768         // entire surface list together before processing to rebase the vertices
7769         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
7770         //
7771         // if any gaps exist and we do not have a static vertex buffer, we have to
7772         // copy the surface list together to avoid wasting upload bandwidth on the
7773         // vertices in the gaps.
7774         //
7775         // if gaps exist and we have a static vertex buffer, we can choose whether
7776         // to combine the index buffer ranges into one dynamic index buffer or
7777         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
7778         //
7779         // in many cases the batch is reduced to one draw call.
7780
7781         rsurface.batchmultidraw = false;
7782         rsurface.batchmultidrawnumsurfaces = 0;
7783         rsurface.batchmultidrawsurfacelist = NULL;
7784
7785         if (!dynamicvertex)
7786         {
7787                 // static vertex data, just set pointers...
7788                 rsurface.batchgeneratedvertex = false;
7789                 // if there are gaps, we want to build a combined index buffer,
7790                 // otherwise use the original static buffer with an appropriate offset
7791                 if (gaps)
7792                 {
7793                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
7794                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
7795                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
7796                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
7797                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
7798                         {
7799                                 rsurface.batchmultidraw = true;
7800                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
7801                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
7802                                 return;
7803                         }
7804                         // build a new triangle elements array for this batch
7805                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7806                         rsurface.batchfirsttriangle = 0;
7807                         numtriangles = 0;
7808                         for (i = 0;i < texturenumsurfaces;i++)
7809                         {
7810                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7811                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7812                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
7813                                 numtriangles += surfacenumtriangles;
7814                         }
7815                         rsurface.batchelement3i_indexbuffer = NULL;
7816                         rsurface.batchelement3i_bufferoffset = 0;
7817                         rsurface.batchelement3s = NULL;
7818                         rsurface.batchelement3s_indexbuffer = NULL;
7819                         rsurface.batchelement3s_bufferoffset = 0;
7820                         if (endvertex <= 65536)
7821                         {
7822                                 // make a 16bit (unsigned short) index array if possible
7823                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7824                                 for (i = 0;i < numtriangles*3;i++)
7825                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7826                         }
7827                         // upload buffer data for the copytriangles batch
7828                         if (rsurface.batchelement3s)
7829                                 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
7830                         else if (rsurface.batchelement3i)
7831                                 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
7832                 }
7833                 else
7834                 {
7835                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
7836                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
7837                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
7838                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
7839                 }
7840                 return;
7841         }
7842
7843         // something needs software processing, do it for real...
7844         // we only directly handle separate array data in this case and then
7845         // generate interleaved data if needed...
7846         rsurface.batchgeneratedvertex = true;
7847         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
7848         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
7849         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
7850         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
7851
7852         // now copy the vertex data into a combined array and make an index array
7853         // (this is what Quake3 does all the time)
7854         // we also apply any skeletal animation here that would have been done in
7855         // the vertex shader, because most of the dynamic vertex animation cases
7856         // need actual vertex positions and normals
7857         //if (dynamicvertex)
7858         {
7859                 rsurface.batchvertex3f = NULL;
7860                 rsurface.batchvertex3f_vertexbuffer = NULL;
7861                 rsurface.batchvertex3f_bufferoffset = 0;
7862                 rsurface.batchsvector3f = NULL;
7863                 rsurface.batchsvector3f_vertexbuffer = NULL;
7864                 rsurface.batchsvector3f_bufferoffset = 0;
7865                 rsurface.batchtvector3f = NULL;
7866                 rsurface.batchtvector3f_vertexbuffer = NULL;
7867                 rsurface.batchtvector3f_bufferoffset = 0;
7868                 rsurface.batchnormal3f = NULL;
7869                 rsurface.batchnormal3f_vertexbuffer = NULL;
7870                 rsurface.batchnormal3f_bufferoffset = 0;
7871                 rsurface.batchlightmapcolor4f = NULL;
7872                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7873                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7874                 rsurface.batchtexcoordtexture2f = NULL;
7875                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7876                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7877                 rsurface.batchtexcoordlightmap2f = NULL;
7878                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7879                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7880                 rsurface.batchskeletalindex4ub = NULL;
7881                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7882                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
7883                 rsurface.batchskeletalweight4ub = NULL;
7884                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7885                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
7886                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7887                 rsurface.batchelement3i_indexbuffer = NULL;
7888                 rsurface.batchelement3i_bufferoffset = 0;
7889                 rsurface.batchelement3s = NULL;
7890                 rsurface.batchelement3s_indexbuffer = NULL;
7891                 rsurface.batchelement3s_bufferoffset = 0;
7892                 rsurface.batchskeletaltransform3x4buffer = NULL;
7893                 rsurface.batchskeletaltransform3x4offset = 0;
7894                 rsurface.batchskeletaltransform3x4size = 0;
7895                 // we'll only be setting up certain arrays as needed
7896                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7897                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7898                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7899                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7900                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7901                 {
7902                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7903                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7904                 }
7905                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7906                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
7907                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7908                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7909                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7910                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7911                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7912                 {
7913                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7914                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7915                 }
7916                 numvertices = 0;
7917                 numtriangles = 0;
7918                 for (i = 0;i < texturenumsurfaces;i++)
7919                 {
7920                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
7921                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
7922                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7923                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7924                         // copy only the data requested
7925                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
7926                         {
7927                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7928                                 {
7929                                         if (rsurface.batchvertex3f)
7930                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7931                                         else
7932                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7933                                 }
7934                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7935                                 {
7936                                         if (rsurface.modelnormal3f)
7937                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7938                                         else
7939                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7940                                 }
7941                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7942                                 {
7943                                         if (rsurface.modelsvector3f)
7944                                         {
7945                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7946                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7947                                         }
7948                                         else
7949                                         {
7950                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7951                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7952                                         }
7953                                 }
7954                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7955                                 {
7956                                         if (rsurface.modellightmapcolor4f)
7957                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
7958                                         else
7959                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
7960                                 }
7961                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7962                                 {
7963                                         if (rsurface.modeltexcoordtexture2f)
7964                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7965                                         else
7966                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7967                                 }
7968                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7969                                 {
7970                                         if (rsurface.modeltexcoordlightmap2f)
7971                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7972                                         else
7973                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7974                                 }
7975                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7976                                 {
7977                                         if (rsurface.modelskeletalindex4ub)
7978                                         {
7979                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7980                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7981                                         }
7982                                         else
7983                                         {
7984                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7985                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7986                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
7987                                                 for (j = 0;j < surfacenumvertices;j++)
7988                                                         ub[j*4] = 255;
7989                                         }
7990                                 }
7991                         }
7992                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
7993                         numvertices += surfacenumvertices;
7994                         numtriangles += surfacenumtriangles;
7995                 }
7996
7997                 // generate a 16bit index array as well if possible
7998                 // (in general, dynamic batches fit)
7999                 if (numvertices <= 65536)
8000                 {
8001                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8002                         for (i = 0;i < numtriangles*3;i++)
8003                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8004                 }
8005
8006                 // since we've copied everything, the batch now starts at 0
8007                 rsurface.batchfirstvertex = 0;
8008                 rsurface.batchnumvertices = batchnumvertices;
8009                 rsurface.batchfirsttriangle = 0;
8010                 rsurface.batchnumtriangles = batchnumtriangles;
8011         }
8012
8013         // apply skeletal animation that would have been done in the vertex shader
8014         if (rsurface.batchskeletaltransform3x4)
8015         {
8016                 const unsigned char *si;
8017                 const unsigned char *sw;
8018                 const float *t[4];
8019                 const float *b = rsurface.batchskeletaltransform3x4;
8020                 float *vp, *vs, *vt, *vn;
8021                 float w[4];
8022                 float m[3][4], n[3][4];
8023                 float tp[3], ts[3], tt[3], tn[3];
8024                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
8025                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
8026                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
8027                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
8028                 si = rsurface.batchskeletalindex4ub;
8029                 sw = rsurface.batchskeletalweight4ub;
8030                 vp = rsurface.batchvertex3f;
8031                 vs = rsurface.batchsvector3f;
8032                 vt = rsurface.batchtvector3f;
8033                 vn = rsurface.batchnormal3f;
8034                 memset(m[0], 0, sizeof(m));
8035                 memset(n[0], 0, sizeof(n));
8036                 for (i = 0;i < batchnumvertices;i++)
8037                 {
8038                         t[0] = b + si[0]*12;
8039                         if (sw[0] == 255)
8040                         {
8041                                 // common case - only one matrix
8042                                 m[0][0] = t[0][ 0];
8043                                 m[0][1] = t[0][ 1];
8044                                 m[0][2] = t[0][ 2];
8045                                 m[0][3] = t[0][ 3];
8046                                 m[1][0] = t[0][ 4];
8047                                 m[1][1] = t[0][ 5];
8048                                 m[1][2] = t[0][ 6];
8049                                 m[1][3] = t[0][ 7];
8050                                 m[2][0] = t[0][ 8];
8051                                 m[2][1] = t[0][ 9];
8052                                 m[2][2] = t[0][10];
8053                                 m[2][3] = t[0][11];
8054                         }
8055                         else if (sw[2] + sw[3])
8056                         {
8057                                 // blend 4 matrices
8058                                 t[1] = b + si[1]*12;
8059                                 t[2] = b + si[2]*12;
8060                                 t[3] = b + si[3]*12;
8061                                 w[0] = sw[0] * (1.0f / 255.0f);
8062                                 w[1] = sw[1] * (1.0f / 255.0f);
8063                                 w[2] = sw[2] * (1.0f / 255.0f);
8064                                 w[3] = sw[3] * (1.0f / 255.0f);
8065                                 // blend the matrices
8066                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
8067                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
8068                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
8069                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
8070                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
8071                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
8072                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
8073                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
8074                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
8075                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
8076                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
8077                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
8078                         }
8079                         else
8080                         {
8081                                 // blend 2 matrices
8082                                 t[1] = b + si[1]*12;
8083                                 w[0] = sw[0] * (1.0f / 255.0f);
8084                                 w[1] = sw[1] * (1.0f / 255.0f);
8085                                 // blend the matrices
8086                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
8087                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
8088                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
8089                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
8090                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
8091                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
8092                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
8093                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
8094                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
8095                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
8096                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
8097                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
8098                         }
8099                         si += 4;
8100                         sw += 4;
8101                         // modify the vertex
8102                         VectorCopy(vp, tp);
8103                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
8104                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
8105                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
8106                         vp += 3;
8107                         if (vn)
8108                         {
8109                                 // the normal transformation matrix is a set of cross products...
8110                                 CrossProduct(m[1], m[2], n[0]);
8111                                 CrossProduct(m[2], m[0], n[1]);
8112                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
8113                                 VectorCopy(vn, tn);
8114                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
8115                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
8116                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
8117                                 VectorNormalize(vn);
8118                                 vn += 3;
8119                                 if (vs)
8120                                 {
8121                                         VectorCopy(vs, ts);
8122                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
8123                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
8124                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
8125                                         VectorNormalize(vs);
8126                                         vs += 3;
8127                                         VectorCopy(vt, tt);
8128                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
8129                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
8130                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
8131                                         VectorNormalize(vt);
8132                                         vt += 3;
8133                                 }
8134                         }
8135                 }
8136                 rsurface.batchskeletaltransform3x4 = NULL;
8137                 rsurface.batchskeletalnumtransforms = 0;
8138         }
8139
8140         // q1bsp surfaces rendered in vertex color mode have to have colors
8141         // calculated based on lightstyles
8142         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
8143         {
8144                 // generate color arrays for the surfaces in this list
8145                 int c[4];
8146                 int scale;
8147                 int size3;
8148                 const int *offsets;
8149                 const unsigned char *lm;
8150                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8151                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8152                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8153                 numvertices = 0;
8154                 for (i = 0;i < texturenumsurfaces;i++)
8155                 {
8156                         surface = texturesurfacelist[i];
8157                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8158                         surfacenumvertices = surface->num_vertices;
8159                         if (surface->lightmapinfo->samples)
8160                         {
8161                                 for (j = 0;j < surfacenumvertices;j++)
8162                                 {
8163                                         lm = surface->lightmapinfo->samples + offsets[j];
8164                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8165                                         VectorScale(lm, scale, c);
8166                                         if (surface->lightmapinfo->styles[1] != 255)
8167                                         {
8168                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8169                                                 lm += size3;
8170                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8171                                                 VectorMA(c, scale, lm, c);
8172                                                 if (surface->lightmapinfo->styles[2] != 255)
8173                                                 {
8174                                                         lm += size3;
8175                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8176                                                         VectorMA(c, scale, lm, c);
8177                                                         if (surface->lightmapinfo->styles[3] != 255)
8178                                                         {
8179                                                                 lm += size3;
8180                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8181                                                                 VectorMA(c, scale, lm, c);
8182                                                         }
8183                                                 }
8184                                         }
8185                                         c[0] >>= 7;
8186                                         c[1] >>= 7;
8187                                         c[2] >>= 7;
8188                                         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);
8189                                         numvertices++;
8190                                 }
8191                         }
8192                         else
8193                         {
8194                                 for (j = 0;j < surfacenumvertices;j++)
8195                                 {
8196                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8197                                         numvertices++;
8198                                 }
8199                         }
8200                 }
8201         }
8202
8203         // if vertices are deformed (sprite flares and things in maps, possibly
8204         // water waves, bulges and other deformations), modify the copied vertices
8205         // in place
8206         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8207         {
8208                 float scale;
8209                 switch (deform->deform)
8210                 {
8211                 default:
8212                 case Q3DEFORM_PROJECTIONSHADOW:
8213                 case Q3DEFORM_TEXT0:
8214                 case Q3DEFORM_TEXT1:
8215                 case Q3DEFORM_TEXT2:
8216                 case Q3DEFORM_TEXT3:
8217                 case Q3DEFORM_TEXT4:
8218                 case Q3DEFORM_TEXT5:
8219                 case Q3DEFORM_TEXT6:
8220                 case Q3DEFORM_TEXT7:
8221                 case Q3DEFORM_NONE:
8222                         break;
8223                 case Q3DEFORM_AUTOSPRITE:
8224                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8225                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8226                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8227                         VectorNormalize(newforward);
8228                         VectorNormalize(newright);
8229                         VectorNormalize(newup);
8230 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8231 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8232 //                      rsurface.batchvertex3f_bufferoffset = 0;
8233 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8234 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8235 //                      rsurface.batchsvector3f_bufferoffset = 0;
8236 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8237 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8238 //                      rsurface.batchtvector3f_bufferoffset = 0;
8239 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8240 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8241 //                      rsurface.batchnormal3f_bufferoffset = 0;
8242                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8243                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8244                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8245                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8246                                 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);
8247                         // a single autosprite surface can contain multiple sprites...
8248                         for (j = 0;j < batchnumvertices - 3;j += 4)
8249                         {
8250                                 VectorClear(center);
8251                                 for (i = 0;i < 4;i++)
8252                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8253                                 VectorScale(center, 0.25f, center);
8254                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8255                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8256                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8257                                 for (i = 0;i < 4;i++)
8258                                 {
8259                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8260                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8261                                 }
8262                         }
8263                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8264                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8265                         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);
8266                         break;
8267                 case Q3DEFORM_AUTOSPRITE2:
8268                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8269                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8270                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8271                         VectorNormalize(newforward);
8272                         VectorNormalize(newright);
8273                         VectorNormalize(newup);
8274 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8275 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8276 //                      rsurface.batchvertex3f_bufferoffset = 0;
8277                         {
8278                                 const float *v1, *v2;
8279                                 vec3_t start, end;
8280                                 float f, l;
8281                                 struct
8282                                 {
8283                                         float length2;
8284                                         const float *v1;
8285                                         const float *v2;
8286                                 }
8287                                 shortest[2];
8288                                 memset(shortest, 0, sizeof(shortest));
8289                                 // a single autosprite surface can contain multiple sprites...
8290                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8291                                 {
8292                                         VectorClear(center);
8293                                         for (i = 0;i < 4;i++)
8294                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8295                                         VectorScale(center, 0.25f, center);
8296                                         // find the two shortest edges, then use them to define the
8297                                         // axis vectors for rotating around the central axis
8298                                         for (i = 0;i < 6;i++)
8299                                         {
8300                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8301                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8302                                                 l = VectorDistance2(v1, v2);
8303                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8304                                                 if (v1[2] != v2[2])
8305                                                         l += (1.0f / 1024.0f);
8306                                                 if (shortest[0].length2 > l || i == 0)
8307                                                 {
8308                                                         shortest[1] = shortest[0];
8309                                                         shortest[0].length2 = l;
8310                                                         shortest[0].v1 = v1;
8311                                                         shortest[0].v2 = v2;
8312                                                 }
8313                                                 else if (shortest[1].length2 > l || i == 1)
8314                                                 {
8315                                                         shortest[1].length2 = l;
8316                                                         shortest[1].v1 = v1;
8317                                                         shortest[1].v2 = v2;
8318                                                 }
8319                                         }
8320                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8321                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8322                                         // this calculates the right vector from the shortest edge
8323                                         // and the up vector from the edge midpoints
8324                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8325                                         VectorNormalize(right);
8326                                         VectorSubtract(end, start, up);
8327                                         VectorNormalize(up);
8328                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8329                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8330                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8331                                         VectorNegate(forward, forward);
8332                                         VectorReflect(forward, 0, up, forward);
8333                                         VectorNormalize(forward);
8334                                         CrossProduct(up, forward, newright);
8335                                         VectorNormalize(newright);
8336                                         // rotate the quad around the up axis vector, this is made
8337                                         // especially easy by the fact we know the quad is flat,
8338                                         // so we only have to subtract the center position and
8339                                         // measure distance along the right vector, and then
8340                                         // multiply that by the newright vector and add back the
8341                                         // center position
8342                                         // we also need to subtract the old position to undo the
8343                                         // displacement from the center, which we do with a
8344                                         // DotProduct, the subtraction/addition of center is also
8345                                         // optimized into DotProducts here
8346                                         l = DotProduct(right, center);
8347                                         for (i = 0;i < 4;i++)
8348                                         {
8349                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8350                                                 f = DotProduct(right, v1) - l;
8351                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8352                                         }
8353                                 }
8354                         }
8355                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8356                         {
8357 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8358 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8359 //                              rsurface.batchnormal3f_bufferoffset = 0;
8360                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8361                         }
8362                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8363                         {
8364 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8365 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8366 //                              rsurface.batchsvector3f_bufferoffset = 0;
8367 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8368 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8369 //                              rsurface.batchtvector3f_bufferoffset = 0;
8370                                 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);
8371                         }
8372                         break;
8373                 case Q3DEFORM_NORMAL:
8374                         // deform the normals to make reflections wavey
8375                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8376                         rsurface.batchnormal3f_vertexbuffer = NULL;
8377                         rsurface.batchnormal3f_bufferoffset = 0;
8378                         for (j = 0;j < batchnumvertices;j++)
8379                         {
8380                                 float vertex[3];
8381                                 float *normal = rsurface.batchnormal3f + 3*j;
8382                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8383                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8384                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8385                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8386                                 VectorNormalize(normal);
8387                         }
8388                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8389                         {
8390 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8391 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8392 //                              rsurface.batchsvector3f_bufferoffset = 0;
8393 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8394 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8395 //                              rsurface.batchtvector3f_bufferoffset = 0;
8396                                 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);
8397                         }
8398                         break;
8399                 case Q3DEFORM_WAVE:
8400                         // deform vertex array to make wavey water and flags and such
8401                         waveparms[0] = deform->waveparms[0];
8402                         waveparms[1] = deform->waveparms[1];
8403                         waveparms[2] = deform->waveparms[2];
8404                         waveparms[3] = deform->waveparms[3];
8405                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8406                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8407                         // this is how a divisor of vertex influence on deformation
8408                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8409                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8410 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8411 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8412 //                      rsurface.batchvertex3f_bufferoffset = 0;
8413 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8414 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8415 //                      rsurface.batchnormal3f_bufferoffset = 0;
8416                         for (j = 0;j < batchnumvertices;j++)
8417                         {
8418                                 // if the wavefunc depends on time, evaluate it per-vertex
8419                                 if (waveparms[3])
8420                                 {
8421                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8422                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8423                                 }
8424                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8425                         }
8426                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8427                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8428                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8429                         {
8430 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8431 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8432 //                              rsurface.batchsvector3f_bufferoffset = 0;
8433 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8434 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8435 //                              rsurface.batchtvector3f_bufferoffset = 0;
8436                                 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);
8437                         }
8438                         break;
8439                 case Q3DEFORM_BULGE:
8440                         // deform vertex array to make the surface have moving bulges
8441 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8442 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8443 //                      rsurface.batchvertex3f_bufferoffset = 0;
8444 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8445 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8446 //                      rsurface.batchnormal3f_bufferoffset = 0;
8447                         for (j = 0;j < batchnumvertices;j++)
8448                         {
8449                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8450                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8451                         }
8452                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8453                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8454                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8455                         {
8456 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8457 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8458 //                              rsurface.batchsvector3f_bufferoffset = 0;
8459 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8460 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8461 //                              rsurface.batchtvector3f_bufferoffset = 0;
8462                                 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);
8463                         }
8464                         break;
8465                 case Q3DEFORM_MOVE:
8466                         // deform vertex array
8467                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8468                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8469                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8470                         VectorScale(deform->parms, scale, waveparms);
8471 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8472 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8473 //                      rsurface.batchvertex3f_bufferoffset = 0;
8474                         for (j = 0;j < batchnumvertices;j++)
8475                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8476                         break;
8477                 }
8478         }
8479
8480         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
8481         {
8482         // generate texcoords based on the chosen texcoord source
8483                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
8484                 {
8485                 default:
8486                 case Q3TCGEN_TEXTURE:
8487                         break;
8488                 case Q3TCGEN_LIGHTMAP:
8489         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8490         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8491         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8492                         if (rsurface.batchtexcoordlightmap2f)
8493                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
8494                         break;
8495                 case Q3TCGEN_VECTOR:
8496         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8497         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8498         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8499                         for (j = 0;j < batchnumvertices;j++)
8500                         {
8501                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
8502                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
8503                         }
8504                         break;
8505                 case Q3TCGEN_ENVIRONMENT:
8506                         // make environment reflections using a spheremap
8507                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8508                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8509                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8510                         for (j = 0;j < batchnumvertices;j++)
8511                         {
8512                                 // identical to Q3A's method, but executed in worldspace so
8513                                 // carried models can be shiny too
8514
8515                                 float viewer[3], d, reflected[3], worldreflected[3];
8516
8517                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8518                                 // VectorNormalize(viewer);
8519
8520                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8521
8522                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8523                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8524                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8525                                 // note: this is proportinal to viewer, so we can normalize later
8526
8527                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8528                                 VectorNormalize(worldreflected);
8529
8530                                 // note: this sphere map only uses world x and z!
8531                                 // so positive and negative y will LOOK THE SAME.
8532                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8533                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8534                         }
8535                         break;
8536                 }
8537                 // the only tcmod that needs software vertex processing is turbulent, so
8538                 // check for it here and apply the changes if needed
8539                 // and we only support that as the first one
8540                 // (handling a mixture of turbulent and other tcmods would be problematic
8541                 //  without punting it entirely to a software path)
8542                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8543                 {
8544                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
8545                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
8546         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8547         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8548         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8549                         for (j = 0;j < batchnumvertices;j++)
8550                         {
8551                                 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);
8552                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8553                         }
8554                 }
8555         }
8556
8557         // upload buffer data for the dynamic batch
8558         if (rsurface.batchvertex3f)
8559                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
8560         if (rsurface.batchsvector3f)
8561                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
8562         if (rsurface.batchtvector3f)
8563                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
8564         if (rsurface.batchnormal3f)
8565                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
8566         if (rsurface.batchlightmapcolor4f)
8567                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
8568         if (rsurface.batchtexcoordtexture2f)
8569                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
8570         if (rsurface.batchtexcoordlightmap2f)
8571                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
8572         if (rsurface.batchskeletalindex4ub)
8573                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
8574         if (rsurface.batchskeletalweight4ub)
8575                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
8576         if (rsurface.batchelement3s)
8577                 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
8578         else if (rsurface.batchelement3i)
8579                 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
8580 }
8581
8582 void RSurf_DrawBatch(void)
8583 {
8584         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8585         // through the pipeline, killing it earlier in the pipeline would have
8586         // per-surface overhead rather than per-batch overhead, so it's best to
8587         // reject it here, before it hits glDraw.
8588         if (rsurface.batchnumtriangles == 0)
8589                 return;
8590 #if 0
8591         // batch debugging code
8592         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8593         {
8594                 int i;
8595                 int j;
8596                 int c;
8597                 const int *e;
8598                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8599                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8600                 {
8601                         c = e[i];
8602                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8603                         {
8604                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8605                                 {
8606                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8607                                                 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);
8608                                         break;
8609                                 }
8610                         }
8611                 }
8612         }
8613 #endif
8614         if (rsurface.batchmultidraw)
8615         {
8616                 // issue multiple draws rather than copying index data
8617                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
8618                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
8619                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
8620                 for (i = 0;i < numsurfaces;)
8621                 {
8622                         // combine consecutive surfaces as one draw
8623                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
8624                                 if (surfacelist[j] != surfacelist[k] + 1)
8625                                         break;
8626                         firstvertex = surfacelist[i]->num_firstvertex;
8627                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
8628                         firsttriangle = surfacelist[i]->num_firsttriangle;
8629                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
8630                         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);
8631                         i = j;
8632                 }
8633         }
8634         else
8635         {
8636                 // there is only one consecutive run of index data (may have been combined)
8637                 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);
8638         }
8639 }
8640
8641 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8642 {
8643         // pick the closest matching water plane
8644         int planeindex, vertexindex, bestplaneindex = -1;
8645         float d, bestd;
8646         vec3_t vert;
8647         const float *v;
8648         r_waterstate_waterplane_t *p;
8649         qboolean prepared = false;
8650         bestd = 0;
8651         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
8652         {
8653                 if(p->camera_entity != rsurface.texture->camera_entity)
8654                         continue;
8655                 d = 0;
8656                 if(!prepared)
8657                 {
8658                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
8659                         prepared = true;
8660                         if(rsurface.batchnumvertices == 0)
8661                                 break;
8662                 }
8663                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8664                 {
8665                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8666                         d += fabs(PlaneDiff(vert, &p->plane));
8667                 }
8668                 if (bestd > d || bestplaneindex < 0)
8669                 {
8670                         bestd = d;
8671                         bestplaneindex = planeindex;
8672                 }
8673         }
8674         return bestplaneindex;
8675         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8676         // this situation though, as it might be better to render single larger
8677         // batches with useless stuff (backface culled for example) than to
8678         // render multiple smaller batches
8679 }
8680
8681 void RSurf_SetupDepthAndCulling(void)
8682 {
8683         // submodels are biased to avoid z-fighting with world surfaces that they
8684         // may be exactly overlapping (avoids z-fighting artifacts on certain
8685         // doors and things in Quake maps)
8686         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8687         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8688         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8689         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8690 }
8691
8692 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8693 {
8694         int i, j;
8695         // transparent sky would be ridiculous
8696         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8697                 return;
8698         R_SetupShader_Generic_NoTexture(false, false);
8699         skyrenderlater = true;
8700         RSurf_SetupDepthAndCulling();
8701         GL_DepthMask(true);
8702
8703         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
8704         if (r_sky_scissor.integer)
8705         {
8706                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8707                 for (i = 0; i < texturenumsurfaces; i++)
8708                 {
8709                         const msurface_t *surf = texturesurfacelist[i];
8710                         const float *v;
8711                         float p[3];
8712                         float mins[3], maxs[3];
8713                         int scissor[4];
8714                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
8715                         {
8716                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
8717                                 if (j > 0)
8718                                 {
8719                                         if (mins[0] > p[0]) mins[0] = p[0];
8720                                         if (mins[1] > p[1]) mins[1] = p[1];
8721                                         if (mins[2] > p[2]) mins[2] = p[2];
8722                                         if (maxs[0] < p[0]) maxs[0] = p[0];
8723                                         if (maxs[1] < p[1]) maxs[1] = p[1];
8724                                         if (maxs[2] < p[2]) maxs[2] = p[2];
8725                                 }
8726                                 else
8727                                 {
8728                                         VectorCopy(p, mins);
8729                                         VectorCopy(p, maxs);
8730                                 }
8731                         }
8732                         if (!R_ScissorForBBox(mins, maxs, scissor))
8733                         {
8734                                 if (skyscissor[2])
8735                                 {
8736                                         if (skyscissor[0] > scissor[0])
8737                                         {
8738                                                 skyscissor[2] += skyscissor[0] - scissor[0];
8739                                                 skyscissor[0] = scissor[0];
8740                                         }
8741                                         if (skyscissor[1] > scissor[1])
8742                                         {
8743                                                 skyscissor[3] += skyscissor[1] - scissor[1];
8744                                                 skyscissor[1] = scissor[1];
8745                                         }
8746                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
8747                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
8748                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
8749                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
8750                                 }
8751                                 else
8752                                         Vector4Copy(scissor, skyscissor);
8753                         }
8754                 }
8755         }
8756
8757         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
8758         // skymasking on them, and Quake3 never did sky masking (unlike
8759         // software Quake and software Quake2), so disable the sky masking
8760         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8761         // and skymasking also looks very bad when noclipping outside the
8762         // level, so don't use it then either.
8763         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)
8764         {
8765                 R_Mesh_ResetTextureState();
8766                 if (skyrendermasked)
8767                 {
8768                         R_SetupShader_DepthOrShadow(false, false, false);
8769                         // depth-only (masking)
8770                         GL_ColorMask(0, 0, 0, 0);
8771                         // just to make sure that braindead drivers don't draw
8772                         // anything despite that colormask...
8773                         GL_BlendFunc(GL_ZERO, GL_ONE);
8774                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8775                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8776                 }
8777                 else
8778                 {
8779                         R_SetupShader_Generic_NoTexture(false, false);
8780                         // fog sky
8781                         GL_BlendFunc(GL_ONE, GL_ZERO);
8782                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
8783                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8784                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
8785                 }
8786                 RSurf_DrawBatch();
8787                 if (skyrendermasked)
8788                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8789         }
8790         R_Mesh_ResetTextureState();
8791         GL_Color(1, 1, 1, 1);
8792 }
8793
8794 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8795 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8796 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8797 {
8798         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
8799                 return;
8800         if (prepass)
8801         {
8802                 // render screenspace normalmap to texture
8803                 GL_DepthMask(true);
8804                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
8805                 RSurf_DrawBatch();
8806                 return;
8807         }
8808
8809         // bind lightmap texture
8810
8811         // water/refraction/reflection/camera surfaces have to be handled specially
8812         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
8813         {
8814                 int start, end, startplaneindex;
8815                 for (start = 0;start < texturenumsurfaces;start = end)
8816                 {
8817                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
8818                         if(startplaneindex < 0)
8819                         {
8820                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
8821                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
8822                                 end = start + 1;
8823                                 continue;
8824                         }
8825                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
8826                                 ;
8827                         // now that we have a batch using the same planeindex, render it
8828                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
8829                         {
8830                                 // render water or distortion background
8831                                 GL_DepthMask(true);
8832                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8833                                 RSurf_DrawBatch();
8834                                 // blend surface on top
8835                                 GL_DepthMask(false);
8836                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
8837                                 RSurf_DrawBatch();
8838                         }
8839                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
8840                         {
8841                                 // render surface with reflection texture as input
8842                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8843                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8844                                 RSurf_DrawBatch();
8845                         }
8846                 }
8847                 return;
8848         }
8849
8850         // render surface batch normally
8851         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8852         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
8853         RSurf_DrawBatch();
8854 }
8855
8856 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8857 {
8858         int vi;
8859         int j;
8860         int texturesurfaceindex;
8861         int k;
8862         const msurface_t *surface;
8863         float surfacecolor4f[4];
8864
8865 //      R_Mesh_ResetTextureState();
8866         R_SetupShader_Generic_NoTexture(false, false);
8867
8868         GL_BlendFunc(GL_ONE, GL_ZERO);
8869         GL_DepthMask(writedepth);
8870
8871         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
8872         vi = 0;
8873         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8874         {
8875                 surface = texturesurfacelist[texturesurfaceindex];
8876                 k = (int)(((size_t)surface) / sizeof(msurface_t));
8877                 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
8878                 for (j = 0;j < surface->num_vertices;j++)
8879                 {
8880                         Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
8881                         vi++;
8882                 }
8883         }
8884         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f);
8885         RSurf_DrawBatch();
8886 }
8887
8888 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8889 {
8890         CHECKGLERROR
8891         RSurf_SetupDepthAndCulling();
8892         if (r_showsurfaces.integer && r_refdef.view.showdebug)
8893         {
8894                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
8895                 return;
8896         }
8897         switch (vid.renderpath)
8898         {
8899         case RENDERPATH_GL32:
8900         case RENDERPATH_GLES2:
8901                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8902                 break;
8903         }
8904         CHECKGLERROR
8905 }
8906
8907 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8908 {
8909         int i, j;
8910         int texturenumsurfaces, endsurface;
8911         texture_t *texture;
8912         const msurface_t *surface;
8913         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
8914
8915         RSurf_ActiveModelEntity(ent, true, true, false);
8916
8917         if (r_transparentdepthmasking.integer)
8918         {
8919                 qboolean setup = false;
8920                 for (i = 0;i < numsurfaces;i = j)
8921                 {
8922                         j = i + 1;
8923                         surface = rsurface.modelsurfaces + surfacelist[i];
8924                         texture = surface->texture;
8925                         rsurface.texture = R_GetCurrentTexture(texture);
8926                         rsurface.lightmaptexture = NULL;
8927                         rsurface.deluxemaptexture = NULL;
8928                         rsurface.uselightmaptexture = false;
8929                         // scan ahead until we find a different texture
8930                         endsurface = min(i + 1024, numsurfaces);
8931                         texturenumsurfaces = 0;
8932                         texturesurfacelist[texturenumsurfaces++] = surface;
8933                         for (;j < endsurface;j++)
8934                         {
8935                                 surface = rsurface.modelsurfaces + surfacelist[j];
8936                                 if (texture != surface->texture)
8937                                         break;
8938                                 texturesurfacelist[texturenumsurfaces++] = surface;
8939                         }
8940                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8941                                 continue;
8942                         // render the range of surfaces as depth
8943                         if (!setup)
8944                         {
8945                                 setup = true;
8946                                 GL_ColorMask(0,0,0,0);
8947                                 GL_Color(1,1,1,1);
8948                                 GL_DepthTest(true);
8949                                 GL_BlendFunc(GL_ONE, GL_ZERO);
8950                                 GL_DepthMask(true);
8951 //                              R_Mesh_ResetTextureState();
8952                         }
8953                         RSurf_SetupDepthAndCulling();
8954                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8955                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8956                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8957                         RSurf_DrawBatch();
8958                 }
8959                 if (setup)
8960                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8961         }
8962
8963         for (i = 0;i < numsurfaces;i = j)
8964         {
8965                 j = i + 1;
8966                 surface = rsurface.modelsurfaces + surfacelist[i];
8967                 texture = surface->texture;
8968                 rsurface.texture = R_GetCurrentTexture(texture);
8969                 // scan ahead until we find a different texture
8970                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
8971                 texturenumsurfaces = 0;
8972                 texturesurfacelist[texturenumsurfaces++] = surface;
8973                 if(FAKELIGHT_ENABLED)
8974                 {
8975                         rsurface.lightmaptexture = NULL;
8976                         rsurface.deluxemaptexture = NULL;
8977                         rsurface.uselightmaptexture = false;
8978                         for (;j < endsurface;j++)
8979                         {
8980                                 surface = rsurface.modelsurfaces + surfacelist[j];
8981                                 if (texture != surface->texture)
8982                                         break;
8983                                 texturesurfacelist[texturenumsurfaces++] = surface;
8984                         }
8985                 }
8986                 else
8987                 {
8988                         rsurface.lightmaptexture = surface->lightmaptexture;
8989                         rsurface.deluxemaptexture = surface->deluxemaptexture;
8990                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8991                         for (;j < endsurface;j++)
8992                         {
8993                                 surface = rsurface.modelsurfaces + surfacelist[j];
8994                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
8995                                         break;
8996                                 texturesurfacelist[texturenumsurfaces++] = surface;
8997                         }
8998                 }
8999                 // render the range of surfaces
9000                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9001         }
9002         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
9003 }
9004
9005 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9006 {
9007         // transparent surfaces get pushed off into the transparent queue
9008         int surfacelistindex;
9009         const msurface_t *surface;
9010         vec3_t tempcenter, center;
9011         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9012         {
9013                 surface = texturesurfacelist[surfacelistindex];
9014                 if (r_transparent_sortsurfacesbynearest.integer)
9015                 {
9016                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
9017                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
9018                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
9019                 }
9020                 else
9021                 {
9022                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9023                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9024                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9025                 }
9026                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9027                 if (rsurface.entity->transparent_offset) // transparent offset
9028                 {
9029                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
9030                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
9031                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
9032                 }
9033                 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);
9034         }
9035 }
9036
9037 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9038 {
9039         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9040                 return;
9041         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9042                 return;
9043         RSurf_SetupDepthAndCulling();
9044         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
9045         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9046         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
9047         RSurf_DrawBatch();
9048 }
9049
9050 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
9051 {
9052         CHECKGLERROR
9053         if (ui)
9054                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9055         else if (depthonly)
9056                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9057         else if (prepass)
9058         {
9059                 if (!rsurface.texture->currentnumlayers)
9060                         return;
9061                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9062                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
9063                 else
9064                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9065         }
9066         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
9067                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9068         else if (!rsurface.texture->currentnumlayers)
9069                 return;
9070         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
9071         {
9072                 // in the deferred case, transparent surfaces were queued during prepass
9073                 if (!r_shadow_usingdeferredprepass)
9074                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
9075         }
9076         else
9077         {
9078                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9079                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9080         }
9081         CHECKGLERROR
9082 }
9083
9084 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
9085 {
9086         int i, j;
9087         texture_t *texture;
9088         R_FrameData_SetMark();
9089         // break the surface list down into batches by texture and use of lightmapping
9090         for (i = 0;i < numsurfaces;i = j)
9091         {
9092                 j = i + 1;
9093                 // texture is the base texture pointer, rsurface.texture is the
9094                 // current frame/skin the texture is directing us to use (for example
9095                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9096                 // use skin 1 instead)
9097                 texture = surfacelist[i]->texture;
9098                 rsurface.texture = R_GetCurrentTexture(texture);
9099                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9100                 {
9101                         // if this texture is not the kind we want, skip ahead to the next one
9102                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9103                                 ;
9104                         continue;
9105                 }
9106                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9107                 {
9108                         rsurface.lightmaptexture = NULL;
9109                         rsurface.deluxemaptexture = NULL;
9110                         rsurface.uselightmaptexture = false;
9111                         // simply scan ahead until we find a different texture or lightmap state
9112                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9113                                 ;
9114                 }
9115                 else
9116                 {
9117                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9118                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9119                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9120                         // simply scan ahead until we find a different texture or lightmap state
9121                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9122                                 ;
9123                 }
9124                 // render the range of surfaces
9125                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass, ui);
9126         }
9127         R_FrameData_ReturnToMark();
9128 }
9129
9130 float locboxvertex3f[6*4*3] =
9131 {
9132         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9133         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9134         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9135         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9136         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9137         1,0,0, 0,0,0, 0,1,0, 1,1,0
9138 };
9139
9140 unsigned short locboxelements[6*2*3] =
9141 {
9142          0, 1, 2, 0, 2, 3,
9143          4, 5, 6, 4, 6, 7,
9144          8, 9,10, 8,10,11,
9145         12,13,14, 12,14,15,
9146         16,17,18, 16,18,19,
9147         20,21,22, 20,22,23
9148 };
9149
9150 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9151 {
9152         int i, j;
9153         cl_locnode_t *loc = (cl_locnode_t *)ent;
9154         vec3_t mins, size;
9155         float vertex3f[6*4*3];
9156         CHECKGLERROR
9157         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9158         GL_DepthMask(false);
9159         GL_DepthRange(0, 1);
9160         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9161         GL_DepthTest(true);
9162         GL_CullFace(GL_NONE);
9163         R_EntityMatrix(&identitymatrix);
9164
9165 //      R_Mesh_ResetTextureState();
9166
9167         i = surfacelist[0];
9168         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9169                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9170                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9171                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9172
9173         if (VectorCompare(loc->mins, loc->maxs))
9174         {
9175                 VectorSet(size, 2, 2, 2);
9176                 VectorMA(loc->mins, -0.5f, size, mins);
9177         }
9178         else
9179         {
9180                 VectorCopy(loc->mins, mins);
9181                 VectorSubtract(loc->maxs, loc->mins, size);
9182         }
9183
9184         for (i = 0;i < 6*4*3;)
9185                 for (j = 0;j < 3;j++, i++)
9186                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9187
9188         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
9189         R_SetupShader_Generic_NoTexture(false, false);
9190         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
9191 }
9192
9193 void R_DrawLocs(void)
9194 {
9195         int index;
9196         cl_locnode_t *loc, *nearestloc;
9197         vec3_t center;
9198         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9199         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9200         {
9201                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9202                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9203         }
9204 }
9205
9206 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9207 {
9208         if (decalsystem->decals)
9209                 Mem_Free(decalsystem->decals);
9210         memset(decalsystem, 0, sizeof(*decalsystem));
9211 }
9212
9213 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)
9214 {
9215         tridecal_t *decal;
9216         tridecal_t *decals;
9217         int i;
9218
9219         // expand or initialize the system
9220         if (decalsystem->maxdecals <= decalsystem->numdecals)
9221         {
9222                 decalsystem_t old = *decalsystem;
9223                 qboolean useshortelements;
9224                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9225                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9226                 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)));
9227                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9228                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9229                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9230                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9231                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9232                 if (decalsystem->numdecals)
9233                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9234                 if (old.decals)
9235                         Mem_Free(old.decals);
9236                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9237                         decalsystem->element3i[i] = i;
9238                 if (useshortelements)
9239                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9240                                 decalsystem->element3s[i] = i;
9241         }
9242
9243         // grab a decal and search for another free slot for the next one
9244         decals = decalsystem->decals;
9245         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9246         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
9247                 ;
9248         decalsystem->freedecal = i;
9249         if (decalsystem->numdecals <= i)
9250                 decalsystem->numdecals = i + 1;
9251
9252         // initialize the decal
9253         decal->lived = 0;
9254         decal->triangleindex = triangleindex;
9255         decal->surfaceindex = surfaceindex;
9256         decal->decalsequence = decalsequence;
9257         decal->color4f[0][0] = c0[0];
9258         decal->color4f[0][1] = c0[1];
9259         decal->color4f[0][2] = c0[2];
9260         decal->color4f[0][3] = 1;
9261         decal->color4f[1][0] = c1[0];
9262         decal->color4f[1][1] = c1[1];
9263         decal->color4f[1][2] = c1[2];
9264         decal->color4f[1][3] = 1;
9265         decal->color4f[2][0] = c2[0];
9266         decal->color4f[2][1] = c2[1];
9267         decal->color4f[2][2] = c2[2];
9268         decal->color4f[2][3] = 1;
9269         decal->vertex3f[0][0] = v0[0];
9270         decal->vertex3f[0][1] = v0[1];
9271         decal->vertex3f[0][2] = v0[2];
9272         decal->vertex3f[1][0] = v1[0];
9273         decal->vertex3f[1][1] = v1[1];
9274         decal->vertex3f[1][2] = v1[2];
9275         decal->vertex3f[2][0] = v2[0];
9276         decal->vertex3f[2][1] = v2[1];
9277         decal->vertex3f[2][2] = v2[2];
9278         decal->texcoord2f[0][0] = t0[0];
9279         decal->texcoord2f[0][1] = t0[1];
9280         decal->texcoord2f[1][0] = t1[0];
9281         decal->texcoord2f[1][1] = t1[1];
9282         decal->texcoord2f[2][0] = t2[0];
9283         decal->texcoord2f[2][1] = t2[1];
9284         TriangleNormal(v0, v1, v2, decal->plane);
9285         VectorNormalize(decal->plane);
9286         decal->plane[3] = DotProduct(v0, decal->plane);
9287 }
9288
9289 extern cvar_t cl_decals_bias;
9290 extern cvar_t cl_decals_models;
9291 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9292 // baseparms, parms, temps
9293 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)
9294 {
9295         int cornerindex;
9296         int index;
9297         float v[9][3];
9298         const float *vertex3f;
9299         const float *normal3f;
9300         int numpoints;
9301         float points[2][9][3];
9302         float temp[3];
9303         float tc[9][2];
9304         float f;
9305         float c[9][4];
9306         const int *e;
9307
9308         e = rsurface.modelelement3i + 3*triangleindex;
9309
9310         vertex3f = rsurface.modelvertex3f;
9311         normal3f = rsurface.modelnormal3f;
9312
9313         if (normal3f)
9314         {
9315                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9316                 {
9317                         index = 3*e[cornerindex];
9318                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
9319                 }
9320         }
9321         else
9322         {
9323                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9324                 {
9325                         index = 3*e[cornerindex];
9326                         VectorCopy(vertex3f + index, v[cornerindex]);
9327                 }
9328         }
9329
9330         // cull backfaces
9331         //TriangleNormal(v[0], v[1], v[2], normal);
9332         //if (DotProduct(normal, localnormal) < 0.0f)
9333         //      continue;
9334         // clip by each of the box planes formed from the projection matrix
9335         // if anything survives, we emit the decal
9336         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]);
9337         if (numpoints < 3)
9338                 return;
9339         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]);
9340         if (numpoints < 3)
9341                 return;
9342         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]);
9343         if (numpoints < 3)
9344                 return;
9345         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]);
9346         if (numpoints < 3)
9347                 return;
9348         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]);
9349         if (numpoints < 3)
9350                 return;
9351         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]);
9352         if (numpoints < 3)
9353                 return;
9354         // some part of the triangle survived, so we have to accept it...
9355         if (dynamic)
9356         {
9357                 // dynamic always uses the original triangle
9358                 numpoints = 3;
9359                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9360                 {
9361                         index = 3*e[cornerindex];
9362                         VectorCopy(vertex3f + index, v[cornerindex]);
9363                 }
9364         }
9365         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9366         {
9367                 // convert vertex positions to texcoords
9368                 Matrix4x4_Transform(projection, v[cornerindex], temp);
9369                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9370                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9371                 // calculate distance fade from the projection origin
9372                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9373                 f = bound(0.0f, f, 1.0f);
9374                 c[cornerindex][0] = r * f;
9375                 c[cornerindex][1] = g * f;
9376                 c[cornerindex][2] = b * f;
9377                 c[cornerindex][3] = 1.0f;
9378                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9379         }
9380         if (dynamic)
9381                 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);
9382         else
9383                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9384                         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);
9385 }
9386 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)
9387 {
9388         matrix4x4_t projection;
9389         decalsystem_t *decalsystem;
9390         qboolean dynamic;
9391         dp_model_t *model;
9392         const msurface_t *surface;
9393         const msurface_t *surfaces;
9394         const int *surfacelist;
9395         const texture_t *texture;
9396         int numtriangles;
9397         int numsurfacelist;
9398         int surfacelistindex;
9399         int surfaceindex;
9400         int triangleindex;
9401         float localorigin[3];
9402         float localnormal[3];
9403         float localmins[3];
9404         float localmaxs[3];
9405         float localsize;
9406         //float normal[3];
9407         float planes[6][4];
9408         float angles[3];
9409         bih_t *bih;
9410         int bih_triangles_count;
9411         int bih_triangles[256];
9412         int bih_surfaces[256];
9413
9414         decalsystem = &ent->decalsystem;
9415         model = ent->model;
9416         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9417         {
9418                 R_DecalSystem_Reset(&ent->decalsystem);
9419                 return;
9420         }
9421
9422         if (!model->brush.data_leafs && !cl_decals_models.integer)
9423         {
9424                 if (decalsystem->model)
9425                         R_DecalSystem_Reset(decalsystem);
9426                 return;
9427         }
9428
9429         if (decalsystem->model != model)
9430                 R_DecalSystem_Reset(decalsystem);
9431         decalsystem->model = model;
9432
9433         RSurf_ActiveModelEntity(ent, true, false, false);
9434
9435         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9436         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9437         VectorNormalize(localnormal);
9438         localsize = worldsize*rsurface.inversematrixscale;
9439         localmins[0] = localorigin[0] - localsize;
9440         localmins[1] = localorigin[1] - localsize;
9441         localmins[2] = localorigin[2] - localsize;
9442         localmaxs[0] = localorigin[0] + localsize;
9443         localmaxs[1] = localorigin[1] + localsize;
9444         localmaxs[2] = localorigin[2] + localsize;
9445
9446         //VectorCopy(localnormal, planes[4]);
9447         //VectorVectors(planes[4], planes[2], planes[0]);
9448         AnglesFromVectors(angles, localnormal, NULL, false);
9449         AngleVectors(angles, planes[0], planes[2], planes[4]);
9450         VectorNegate(planes[0], planes[1]);
9451         VectorNegate(planes[2], planes[3]);
9452         VectorNegate(planes[4], planes[5]);
9453         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9454         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9455         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9456         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9457         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9458         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9459
9460 #if 1
9461 // works
9462 {
9463         matrix4x4_t forwardprojection;
9464         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9465         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9466 }
9467 #else
9468 // broken
9469 {
9470         float projectionvector[4][3];
9471         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9472         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9473         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9474         projectionvector[0][0] = planes[0][0] * ilocalsize;
9475         projectionvector[0][1] = planes[1][0] * ilocalsize;
9476         projectionvector[0][2] = planes[2][0] * ilocalsize;
9477         projectionvector[1][0] = planes[0][1] * ilocalsize;
9478         projectionvector[1][1] = planes[1][1] * ilocalsize;
9479         projectionvector[1][2] = planes[2][1] * ilocalsize;
9480         projectionvector[2][0] = planes[0][2] * ilocalsize;
9481         projectionvector[2][1] = planes[1][2] * ilocalsize;
9482         projectionvector[2][2] = planes[2][2] * ilocalsize;
9483         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9484         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9485         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9486         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9487 }
9488 #endif
9489
9490         dynamic = model->surfmesh.isanimated;
9491         numsurfacelist = model->nummodelsurfaces;
9492         surfacelist = model->sortedmodelsurfaces;
9493         surfaces = model->data_surfaces;
9494
9495         bih = NULL;
9496         bih_triangles_count = -1;
9497         if(!dynamic)
9498         {
9499                 if(model->render_bih.numleafs)
9500                         bih = &model->render_bih;
9501                 else if(model->collision_bih.numleafs)
9502                         bih = &model->collision_bih;
9503         }
9504         if(bih)
9505                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
9506         if(bih_triangles_count == 0)
9507                 return;
9508         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
9509                 return;
9510         if(bih_triangles_count > 0)
9511         {
9512                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
9513                 {
9514                         surfaceindex = bih_surfaces[triangleindex];
9515                         surface = surfaces + surfaceindex;
9516                         texture = surface->texture;
9517                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9518                                 continue;
9519                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9520                                 continue;
9521                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
9522                 }
9523         }
9524         else
9525         {
9526                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9527                 {
9528                         surfaceindex = surfacelist[surfacelistindex];
9529                         surface = surfaces + surfaceindex;
9530                         // check cull box first because it rejects more than any other check
9531                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9532                                 continue;
9533                         // skip transparent surfaces
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                         numtriangles = surface->num_triangles;
9540                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
9541                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
9542                 }
9543         }
9544 }
9545
9546 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9547 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)
9548 {
9549         int renderentityindex;
9550         float worldmins[3];
9551         float worldmaxs[3];
9552         entity_render_t *ent;
9553
9554         if (!cl_decals_newsystem.integer)
9555                 return;
9556
9557         worldmins[0] = worldorigin[0] - worldsize;
9558         worldmins[1] = worldorigin[1] - worldsize;
9559         worldmins[2] = worldorigin[2] - worldsize;
9560         worldmaxs[0] = worldorigin[0] + worldsize;
9561         worldmaxs[1] = worldorigin[1] + worldsize;
9562         worldmaxs[2] = worldorigin[2] + worldsize;
9563
9564         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9565
9566         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9567         {
9568                 ent = r_refdef.scene.entities[renderentityindex];
9569                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9570                         continue;
9571
9572                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9573         }
9574 }
9575
9576 typedef struct r_decalsystem_splatqueue_s
9577 {
9578         vec3_t worldorigin;
9579         vec3_t worldnormal;
9580         float color[4];
9581         float tcrange[4];
9582         float worldsize;
9583         unsigned int decalsequence;
9584 }
9585 r_decalsystem_splatqueue_t;
9586
9587 int r_decalsystem_numqueued = 0;
9588 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9589
9590 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)
9591 {
9592         r_decalsystem_splatqueue_t *queue;
9593
9594         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9595                 return;
9596
9597         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9598         VectorCopy(worldorigin, queue->worldorigin);
9599         VectorCopy(worldnormal, queue->worldnormal);
9600         Vector4Set(queue->color, r, g, b, a);
9601         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9602         queue->worldsize = worldsize;
9603         queue->decalsequence = cl.decalsequence++;
9604 }
9605
9606 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9607 {
9608         int i;
9609         r_decalsystem_splatqueue_t *queue;
9610
9611         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9612                 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);
9613         r_decalsystem_numqueued = 0;
9614 }
9615
9616 extern cvar_t cl_decals_max;
9617 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9618 {
9619         int i;
9620         decalsystem_t *decalsystem = &ent->decalsystem;
9621         int numdecals;
9622         unsigned int killsequence;
9623         tridecal_t *decal;
9624         float frametime;
9625         float lifetime;
9626
9627         if (!decalsystem->numdecals)
9628                 return;
9629
9630         if (r_showsurfaces.integer)
9631                 return;
9632
9633         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9634         {
9635                 R_DecalSystem_Reset(decalsystem);
9636                 return;
9637         }
9638
9639         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
9640         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9641
9642         if (decalsystem->lastupdatetime)
9643                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
9644         else
9645                 frametime = 0;
9646         decalsystem->lastupdatetime = r_refdef.scene.time;
9647         numdecals = decalsystem->numdecals;
9648
9649         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9650         {
9651                 if (decal->color4f[0][3])
9652                 {
9653                         decal->lived += frametime;
9654                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
9655                         {
9656                                 memset(decal, 0, sizeof(*decal));
9657                                 if (decalsystem->freedecal > i)
9658                                         decalsystem->freedecal = i;
9659                         }
9660                 }
9661         }
9662         decal = decalsystem->decals;
9663         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
9664                 numdecals--;
9665
9666         // collapse the array by shuffling the tail decals into the gaps
9667         for (;;)
9668         {
9669                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
9670                         decalsystem->freedecal++;
9671                 if (decalsystem->freedecal == numdecals)
9672                         break;
9673                 decal[decalsystem->freedecal] = decal[--numdecals];
9674         }
9675
9676         decalsystem->numdecals = numdecals;
9677
9678         if (numdecals <= 0)
9679         {
9680                 // if there are no decals left, reset decalsystem
9681                 R_DecalSystem_Reset(decalsystem);
9682         }
9683 }
9684
9685 extern skinframe_t *decalskinframe;
9686 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9687 {
9688         int i;
9689         decalsystem_t *decalsystem = &ent->decalsystem;
9690         int numdecals;
9691         tridecal_t *decal;
9692         float faderate;
9693         float alpha;
9694         float *v3f;
9695         float *c4f;
9696         float *t2f;
9697         const int *e;
9698         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9699         int numtris = 0;
9700
9701         numdecals = decalsystem->numdecals;
9702         if (!numdecals)
9703                 return;
9704
9705         if (r_showsurfaces.integer)
9706                 return;
9707
9708         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9709         {
9710                 R_DecalSystem_Reset(decalsystem);
9711                 return;
9712         }
9713
9714         // if the model is static it doesn't matter what value we give for
9715         // wantnormals and wanttangents, so this logic uses only rules applicable
9716         // to a model, knowing that they are meaningless otherwise
9717         RSurf_ActiveModelEntity(ent, false, false, false);
9718
9719         decalsystem->lastupdatetime = r_refdef.scene.time;
9720
9721         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9722
9723         // update vertex positions for animated models
9724         v3f = decalsystem->vertex3f;
9725         c4f = decalsystem->color4f;
9726         t2f = decalsystem->texcoord2f;
9727         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9728         {
9729                 if (!decal->color4f[0][3])
9730                         continue;
9731
9732                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9733                         continue;
9734
9735                 // skip backfaces
9736                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
9737                         continue;
9738
9739                 // update color values for fading decals
9740                 if (decal->lived >= cl_decals_time.value)
9741                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9742                 else
9743                         alpha = 1.0f;
9744
9745                 c4f[ 0] = decal->color4f[0][0] * alpha;
9746                 c4f[ 1] = decal->color4f[0][1] * alpha;
9747                 c4f[ 2] = decal->color4f[0][2] * alpha;
9748                 c4f[ 3] = 1;
9749                 c4f[ 4] = decal->color4f[1][0] * alpha;
9750                 c4f[ 5] = decal->color4f[1][1] * alpha;
9751                 c4f[ 6] = decal->color4f[1][2] * alpha;
9752                 c4f[ 7] = 1;
9753                 c4f[ 8] = decal->color4f[2][0] * alpha;
9754                 c4f[ 9] = decal->color4f[2][1] * alpha;
9755                 c4f[10] = decal->color4f[2][2] * alpha;
9756                 c4f[11] = 1;
9757
9758                 t2f[0] = decal->texcoord2f[0][0];
9759                 t2f[1] = decal->texcoord2f[0][1];
9760                 t2f[2] = decal->texcoord2f[1][0];
9761                 t2f[3] = decal->texcoord2f[1][1];
9762                 t2f[4] = decal->texcoord2f[2][0];
9763                 t2f[5] = decal->texcoord2f[2][1];
9764
9765                 // update vertex positions for animated models
9766                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
9767                 {
9768                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9769                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
9770                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
9771                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
9772                 }
9773                 else
9774                 {
9775                         VectorCopy(decal->vertex3f[0], v3f);
9776                         VectorCopy(decal->vertex3f[1], v3f + 3);
9777                         VectorCopy(decal->vertex3f[2], v3f + 6);
9778                 }
9779
9780                 if (r_refdef.fogenabled)
9781                 {
9782                         alpha = RSurf_FogVertex(v3f);
9783                         VectorScale(c4f, alpha, c4f);
9784                         alpha = RSurf_FogVertex(v3f + 3);
9785                         VectorScale(c4f + 4, alpha, c4f + 4);
9786                         alpha = RSurf_FogVertex(v3f + 6);
9787                         VectorScale(c4f + 8, alpha, c4f + 8);
9788                 }
9789
9790                 v3f += 9;
9791                 c4f += 12;
9792                 t2f += 6;
9793                 numtris++;
9794         }
9795
9796         if (numtris > 0)
9797         {
9798                 r_refdef.stats[r_stat_drawndecals] += numtris;
9799
9800                 // now render the decals all at once
9801                 // (this assumes they all use one particle font texture!)
9802                 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);
9803 //              R_Mesh_ResetTextureState();
9804                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
9805                 GL_DepthMask(false);
9806                 GL_DepthRange(0, 1);
9807                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9808                 GL_DepthTest(true);
9809                 GL_CullFace(GL_NONE);
9810                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9811                 R_SetupShader_Generic(decalskinframe->base, false, false, false);
9812                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
9813         }
9814 }
9815
9816 static void R_DrawModelDecals(void)
9817 {
9818         int i, numdecals;
9819
9820         // fade faster when there are too many decals
9821         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9822         for (i = 0;i < r_refdef.scene.numentities;i++)
9823                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9824
9825         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9826         for (i = 0;i < r_refdef.scene.numentities;i++)
9827                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9828                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9829
9830         R_DecalSystem_ApplySplatEntitiesQueue();
9831
9832         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9833         for (i = 0;i < r_refdef.scene.numentities;i++)
9834                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9835
9836         r_refdef.stats[r_stat_totaldecals] += numdecals;
9837
9838         if (r_showsurfaces.integer)
9839                 return;
9840
9841         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9842
9843         for (i = 0;i < r_refdef.scene.numentities;i++)
9844         {
9845                 if (!r_refdef.viewcache.entityvisible[i])
9846                         continue;
9847                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9848                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9849         }
9850 }
9851
9852 extern cvar_t mod_collision_bih;
9853 static void R_DrawDebugModel(void)
9854 {
9855         entity_render_t *ent = rsurface.entity;
9856         int i, j, flagsmask;
9857         const msurface_t *surface;
9858         dp_model_t *model = ent->model;
9859
9860         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
9861                 return;
9862
9863         if (r_showoverdraw.value > 0)
9864         {
9865                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
9866                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9867                 R_SetupShader_Generic_NoTexture(false, false);
9868                 GL_DepthTest(false);
9869                 GL_DepthMask(false);
9870                 GL_DepthRange(0, 1);
9871                 GL_BlendFunc(GL_ONE, GL_ONE);
9872                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9873                 {
9874                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9875                                 continue;
9876                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9877                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9878                         {
9879                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9880                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9881                                 if (!rsurface.texture->currentlayers->depthmask)
9882                                         GL_Color(c, 0, 0, 1.0f);
9883                                 else if (ent == r_refdef.scene.worldentity)
9884                                         GL_Color(c, c, c, 1.0f);
9885                                 else
9886                                         GL_Color(0, c, 0, 1.0f);
9887                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9888                                 RSurf_DrawBatch();
9889                         }
9890                 }
9891                 rsurface.texture = NULL;
9892         }
9893
9894         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9895
9896 //      R_Mesh_ResetTextureState();
9897         R_SetupShader_Generic_NoTexture(false, false);
9898         GL_DepthRange(0, 1);
9899         GL_DepthTest(!r_showdisabledepthtest.integer);
9900         GL_DepthMask(false);
9901         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9902
9903         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
9904         {
9905                 int triangleindex;
9906                 int bihleafindex;
9907                 qboolean cullbox = false;
9908                 const q3mbrush_t *brush;
9909                 const bih_t *bih = &model->collision_bih;
9910                 const bih_leaf_t *bihleaf;
9911                 float vertex3f[3][3];
9912                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9913                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
9914                 {
9915                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
9916                                 continue;
9917                         switch (bihleaf->type)
9918                         {
9919                         case BIH_BRUSH:
9920                                 brush = model->brush.data_brushes + bihleaf->itemindex;
9921                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
9922                                 {
9923                                         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);
9924                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
9925                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
9926                                 }
9927                                 break;
9928                         case BIH_COLLISIONTRIANGLE:
9929                                 triangleindex = bihleaf->itemindex;
9930                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
9931                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
9932                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
9933                                 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);
9934                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9935                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9936                                 break;
9937                         case BIH_RENDERTRIANGLE:
9938                                 triangleindex = bihleaf->itemindex;
9939                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
9940                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
9941                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
9942                                 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);
9943                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9944                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9945                                 break;
9946                         }
9947                 }
9948         }
9949
9950         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9951
9952 #ifndef USE_GLES2
9953         if (r_showtris.value > 0 && qglPolygonMode)
9954         {
9955                 if (r_showdisabledepthtest.integer)
9956                 {
9957                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9958                         GL_DepthMask(false);
9959                 }
9960                 else
9961                 {
9962                         GL_BlendFunc(GL_ONE, GL_ZERO);
9963                         GL_DepthMask(true);
9964                 }
9965                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
9966                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9967                 {
9968                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9969                                 continue;
9970                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9971                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9972                         {
9973                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9974                                 if (!rsurface.texture->currentlayers->depthmask)
9975                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9976                                 else if (ent == r_refdef.scene.worldentity)
9977                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9978                                 else
9979                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9980                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9981                                 RSurf_DrawBatch();
9982                         }
9983                 }
9984                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
9985                 rsurface.texture = NULL;
9986         }
9987
9988 # if 0
9989         // FIXME!  implement r_shownormals with just triangles
9990         if (r_shownormals.value != 0 && qglBegin)
9991         {
9992                 int l, k;
9993                 vec3_t v;
9994                 if (r_showdisabledepthtest.integer)
9995                 {
9996                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9997                         GL_DepthMask(false);
9998                 }
9999                 else
10000                 {
10001                         GL_BlendFunc(GL_ONE, GL_ZERO);
10002                         GL_DepthMask(true);
10003                 }
10004                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10005                 {
10006                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10007                                 continue;
10008                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10009                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10010                         {
10011                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10012                                 qglBegin(GL_LINES);
10013                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
10014                                 {
10015                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10016                                         {
10017                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10018                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10019                                                 qglVertex3f(v[0], v[1], v[2]);
10020                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10021                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10022                                                 qglVertex3f(v[0], v[1], v[2]);
10023                                         }
10024                                 }
10025                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10026                                 {
10027                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10028                                         {
10029                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10030                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10031                                                 qglVertex3f(v[0], v[1], v[2]);
10032                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10033                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10034                                                 qglVertex3f(v[0], v[1], v[2]);
10035                                         }
10036                                 }
10037                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
10038                                 {
10039                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10040                                         {
10041                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10042                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10043                                                 qglVertex3f(v[0], v[1], v[2]);
10044                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10045                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10046                                                 qglVertex3f(v[0], v[1], v[2]);
10047                                         }
10048                                 }
10049                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
10050                                 {
10051                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10052                                         {
10053                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10054                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10055                                                 qglVertex3f(v[0], v[1], v[2]);
10056                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10057                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10058                                                 qglVertex3f(v[0], v[1], v[2]);
10059                                         }
10060                                 }
10061                                 qglEnd();
10062                                 CHECKGLERROR
10063                         }
10064                 }
10065                 rsurface.texture = NULL;
10066         }
10067 # endif
10068 #endif
10069 }
10070
10071 int r_maxsurfacelist = 0;
10072 const msurface_t **r_surfacelist = NULL;
10073 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass, qboolean ui)
10074 {
10075         int i, j, endj, flagsmask;
10076         dp_model_t *model = ent->model;
10077         msurface_t *surfaces;
10078         unsigned char *update;
10079         int numsurfacelist = 0;
10080         if (model == NULL)
10081                 return;
10082
10083         if (r_maxsurfacelist < model->num_surfaces)
10084         {
10085                 r_maxsurfacelist = model->num_surfaces;
10086                 if (r_surfacelist)
10087                         Mem_Free((msurface_t **)r_surfacelist);
10088                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10089         }
10090
10091         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10092                 RSurf_ActiveModelEntity(ent, false, false, false);
10093         else if (prepass)
10094                 RSurf_ActiveModelEntity(ent, true, true, true);
10095         else if (depthonly)
10096                 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
10097         else
10098                 RSurf_ActiveModelEntity(ent, true, true, false);
10099
10100         surfaces = model->data_surfaces;
10101         update = model->brushq1.lightmapupdateflags;
10102
10103         // update light styles
10104         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
10105         {
10106                 model_brush_lightstyleinfo_t *style;
10107                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10108                 {
10109                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10110                         {
10111                                 int *list = style->surfacelist;
10112                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10113                                 for (j = 0;j < style->numsurfaces;j++)
10114                                         update[list[j]] = true;
10115                         }
10116                 }
10117         }
10118
10119         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10120
10121         if (debug)
10122         {
10123                 R_DrawDebugModel();
10124                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10125                 return;
10126         }
10127
10128         rsurface.lightmaptexture = NULL;
10129         rsurface.deluxemaptexture = NULL;
10130         rsurface.uselightmaptexture = false;
10131         rsurface.texture = NULL;
10132         rsurface.rtlight = NULL;
10133         numsurfacelist = 0;
10134         // add visible surfaces to draw list
10135         if (ent == r_refdef.scene.worldentity)
10136         {
10137                 // for the world entity, check surfacevisible
10138                 for (i = 0;i < model->nummodelsurfaces;i++)
10139                 {
10140                         j = model->sortedmodelsurfaces[i];
10141                         if (r_refdef.viewcache.world_surfacevisible[j])
10142                                 r_surfacelist[numsurfacelist++] = surfaces + j;
10143                 }
10144         }
10145         else if (ui)
10146         {
10147                 // for ui we have to preserve the order of surfaces
10148                 for (i = 0; i < model->nummodelsurfaces; i++)
10149                         r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i;
10150         }
10151         else
10152         {
10153                 // add all surfaces
10154                 for (i = 0; i < model->nummodelsurfaces; i++)
10155                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10156         }
10157         // don't do anything if there were no surfaces
10158         if (!numsurfacelist)
10159         {
10160                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10161                 return;
10162         }
10163         // update lightmaps if needed
10164         if (update)
10165         {
10166                 int updated = 0;
10167                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10168                 {
10169                         if (update[j])
10170                         {
10171                                 updated++;
10172                                 R_BuildLightMap(ent, surfaces + j);
10173                         }
10174                 }
10175         }
10176
10177         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass, ui);
10178
10179         // add to stats if desired
10180         if (r_speeds.integer && !skysurfaces && !depthonly)
10181         {
10182                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
10183                 for (j = 0;j < numsurfacelist;j++)
10184                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
10185         }
10186
10187         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10188 }
10189
10190 void R_DebugLine(vec3_t start, vec3_t end)
10191 {
10192         dp_model_t *mod = CL_Mesh_UI();
10193         msurface_t *surf;
10194         int e0, e1, e2, e3;
10195         float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
10196         float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
10197         float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
10198         vec4_t w[2], s[2];
10199
10200         // transform to screen coords first
10201         Vector4Set(w[0], start[0], start[1], start[2], 1);
10202         Vector4Set(w[1], end[0], end[1], end[2], 1);
10203         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
10204         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
10205         x1 = s[0][0] * vid_conwidth.value / vid.width;
10206         y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
10207         x2 = s[1][0] * vid_conwidth.value / vid.width;
10208         y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
10209         //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
10210
10211         // add the line to the UI mesh for drawing later
10212
10213         // width is measured in real pixels
10214         if (fabs(x2 - x1) > fabs(y2 - y1))
10215         {
10216                 offsetx = 0;
10217                 offsety = 0.5f * width * vid_conheight.value / vid.height;
10218         }
10219         else
10220         {
10221                 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
10222                 offsety = 0;
10223         }
10224         surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX), true);
10225         e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10226         e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10227         e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10228         e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10229         Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
10230         Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
10231
10232 }
10233
10234
10235 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10236 {
10237         int q;
10238         static texture_t texture;
10239         static msurface_t surface;
10240         const msurface_t *surfacelist = &surface;
10241
10242         // fake enough texture and surface state to render this geometry
10243
10244         texture.update_lastrenderframe = -1; // regenerate this texture
10245         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10246         texture.basealpha = 1.0f;
10247         texture.currentskinframe = skinframe;
10248         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10249         texture.offsetmapping = OFFSETMAPPING_OFF;
10250         texture.offsetscale = 1;
10251         texture.specularscalemod = 1;
10252         texture.specularpowermod = 1;
10253         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
10254         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
10255         // JUST GREP FOR "specularscalemod = 1".
10256
10257         for (q = 0; q < 3; q++)
10258         {
10259                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
10260                 texture.render_modellight_lightdir[q] = q == 2;
10261                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10262                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
10263                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
10264                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10265                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
10266                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
10267                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
10268                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
10269         }
10270         texture.currentalpha = 1.0f;
10271
10272         surface.texture = &texture;
10273         surface.num_triangles = numtriangles;
10274         surface.num_firsttriangle = firsttriangle;
10275         surface.num_vertices = numvertices;
10276         surface.num_firstvertex = firstvertex;
10277
10278         // now render it
10279         rsurface.texture = R_GetCurrentTexture(surface.texture);
10280         rsurface.lightmaptexture = NULL;
10281         rsurface.deluxemaptexture = NULL;
10282         rsurface.uselightmaptexture = false;
10283         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10284 }
10285
10286 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)
10287 {
10288         static msurface_t surface;
10289         const msurface_t *surfacelist = &surface;
10290
10291         // fake enough texture and surface state to render this geometry
10292         surface.texture = texture;
10293         surface.num_triangles = numtriangles;
10294         surface.num_firsttriangle = firsttriangle;
10295         surface.num_vertices = numvertices;
10296         surface.num_firstvertex = firstvertex;
10297
10298         // now render it
10299         rsurface.texture = R_GetCurrentTexture(surface.texture);
10300         rsurface.lightmaptexture = NULL;
10301         rsurface.deluxemaptexture = NULL;
10302         rsurface.uselightmaptexture = false;
10303         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10304 }