]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Remove code for r_fakelight.
[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_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"};
121 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
122 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
123 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"};
124 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"};
125
126 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
127 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
128 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
129 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."};
130 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
131 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
132 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
133 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."};
134 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
135 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
136 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."};
137 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."};
138 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
139 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"};
140 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"};
141 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
142 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
143 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
144 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
145 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
146 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"};
147 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
148 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
149 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
150 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
151 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
152
153 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
154 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
155 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
156 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
157 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
158 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
159 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
160 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
161
162 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)"};
163 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"};
164
165 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
166 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
167 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
168
169 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"};
170 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"};
171 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)"};
172 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"};
173 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
174 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
175 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"};
176 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)"};
177 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)"};
178 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
179
180 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
181 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)"};
182 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
185 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)"};
186 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)"};
187 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
188 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"};
189 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."};
190 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199
200 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)"};
201 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)"};
202 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
203 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"};
204 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
205 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
206 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
207 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"};
208 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"};
209
210 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
211 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
212 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
213 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
214
215 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
216 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
217
218 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
219 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
220 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
221 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
222 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
223 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
224
225 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
226 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
227 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
228 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
229 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
230 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
231 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
232 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
233 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
234 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
235
236 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"};
237
238 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"};
239
240 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
241
242 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
243
244 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)"};
245 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)"};
246 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
247 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
248
249 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
250 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"};
251
252 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."};
253
254 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)"};
255 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
256 {
257         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
258         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
259         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
260         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
261 };
262
263 extern cvar_t v_glslgamma_2d;
264
265 extern qboolean v_flipped_state;
266
267 r_framebufferstate_t r_fb;
268
269 /// shadow volume bsp struct with automatically growing nodes buffer
270 svbsp_t r_svbsp;
271
272 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
273
274 rtexture_t *r_texture_blanknormalmap;
275 rtexture_t *r_texture_white;
276 rtexture_t *r_texture_grey128;
277 rtexture_t *r_texture_black;
278 rtexture_t *r_texture_notexture;
279 rtexture_t *r_texture_whitecube;
280 rtexture_t *r_texture_normalizationcube;
281 rtexture_t *r_texture_fogattenuation;
282 rtexture_t *r_texture_fogheighttexture;
283 rtexture_t *r_texture_gammaramps;
284 unsigned int r_texture_gammaramps_serial;
285 //rtexture_t *r_texture_fogintensity;
286 rtexture_t *r_texture_reflectcube;
287
288 // TODO: hash lookups?
289 typedef struct cubemapinfo_s
290 {
291         char basename[64];
292         rtexture_t *texture;
293 }
294 cubemapinfo_t;
295
296 int r_texture_numcubemaps;
297 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
298
299 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
300 unsigned int r_numqueries;
301 unsigned int r_maxqueries;
302
303 typedef struct r_qwskincache_s
304 {
305         char name[MAX_QPATH];
306         skinframe_t *skinframe;
307 }
308 r_qwskincache_t;
309
310 static r_qwskincache_t *r_qwskincache;
311 static int r_qwskincache_size;
312
313 /// vertex coordinates for a quad that covers the screen exactly
314 extern const float r_screenvertex3f[12];
315 const float r_screenvertex3f[12] =
316 {
317         0, 0, 0,
318         1, 0, 0,
319         1, 1, 0,
320         0, 1, 0
321 };
322
323 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
324 {
325         int i;
326         for (i = 0;i < verts;i++)
327         {
328                 out[0] = in[0] * r;
329                 out[1] = in[1] * g;
330                 out[2] = in[2] * b;
331                 out[3] = in[3];
332                 in += 4;
333                 out += 4;
334         }
335 }
336
337 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
338 {
339         int i;
340         for (i = 0;i < verts;i++)
341         {
342                 out[0] = r;
343                 out[1] = g;
344                 out[2] = b;
345                 out[3] = a;
346                 out += 4;
347         }
348 }
349
350 // FIXME: move this to client?
351 void FOG_clear(void)
352 {
353         if (gamemode == GAME_NEHAHRA)
354         {
355                 Cvar_Set("gl_fogenable", "0");
356                 Cvar_Set("gl_fogdensity", "0.2");
357                 Cvar_Set("gl_fogred", "0.3");
358                 Cvar_Set("gl_foggreen", "0.3");
359                 Cvar_Set("gl_fogblue", "0.3");
360         }
361         r_refdef.fog_density = 0;
362         r_refdef.fog_red = 0;
363         r_refdef.fog_green = 0;
364         r_refdef.fog_blue = 0;
365         r_refdef.fog_alpha = 1;
366         r_refdef.fog_start = 0;
367         r_refdef.fog_end = 16384;
368         r_refdef.fog_height = 1<<30;
369         r_refdef.fog_fadedepth = 128;
370         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
371 }
372
373 static void R_BuildBlankTextures(void)
374 {
375         unsigned char data[4];
376         data[2] = 128; // normal X
377         data[1] = 128; // normal Y
378         data[0] = 255; // normal Z
379         data[3] = 255; // height
380         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 255;
382         data[1] = 255;
383         data[2] = 255;
384         data[3] = 255;
385         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 128;
387         data[1] = 128;
388         data[2] = 128;
389         data[3] = 255;
390         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391         data[0] = 0;
392         data[1] = 0;
393         data[2] = 0;
394         data[3] = 255;
395         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNoTexture(void)
399 {
400         int x, y;
401         unsigned char pix[16][16][4];
402         // this makes a light grey/dark grey checkerboard texture
403         for (y = 0;y < 16;y++)
404         {
405                 for (x = 0;x < 16;x++)
406                 {
407                         if ((y < 8) ^ (x < 8))
408                         {
409                                 pix[y][x][0] = 128;
410                                 pix[y][x][1] = 128;
411                                 pix[y][x][2] = 128;
412                                 pix[y][x][3] = 255;
413                         }
414                         else
415                         {
416                                 pix[y][x][0] = 64;
417                                 pix[y][x][1] = 64;
418                                 pix[y][x][2] = 64;
419                                 pix[y][x][3] = 255;
420                         }
421                 }
422         }
423         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
424 }
425
426 static void R_BuildWhiteCube(void)
427 {
428         unsigned char data[6*1*1*4];
429         memset(data, 255, sizeof(data));
430         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildNormalizationCube(void)
434 {
435         int x, y, side;
436         vec3_t v;
437         vec_t s, t, intensity;
438 #define NORMSIZE 64
439         unsigned char *data;
440         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
441         for (side = 0;side < 6;side++)
442         {
443                 for (y = 0;y < NORMSIZE;y++)
444                 {
445                         for (x = 0;x < NORMSIZE;x++)
446                         {
447                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449                                 switch(side)
450                                 {
451                                 default:
452                                 case 0:
453                                         v[0] = 1;
454                                         v[1] = -t;
455                                         v[2] = -s;
456                                         break;
457                                 case 1:
458                                         v[0] = -1;
459                                         v[1] = -t;
460                                         v[2] = s;
461                                         break;
462                                 case 2:
463                                         v[0] = s;
464                                         v[1] = 1;
465                                         v[2] = t;
466                                         break;
467                                 case 3:
468                                         v[0] = s;
469                                         v[1] = -1;
470                                         v[2] = -t;
471                                         break;
472                                 case 4:
473                                         v[0] = s;
474                                         v[1] = -t;
475                                         v[2] = 1;
476                                         break;
477                                 case 5:
478                                         v[0] = -s;
479                                         v[1] = -t;
480                                         v[2] = -1;
481                                         break;
482                                 }
483                                 intensity = 127.0f / sqrt(DotProduct(v, v));
484                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
485                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
486                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
487                                 data[((side*64+y)*64+x)*4+3] = 255;
488                         }
489                 }
490         }
491         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492         Mem_Free(data);
493 }
494
495 static void R_BuildFogTexture(void)
496 {
497         int x, b;
498 #define FOGWIDTH 256
499         unsigned char data1[FOGWIDTH][4];
500         //unsigned char data2[FOGWIDTH][4];
501         double d, r, alpha;
502
503         r_refdef.fogmasktable_start = r_refdef.fog_start;
504         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
505         r_refdef.fogmasktable_range = r_refdef.fogrange;
506         r_refdef.fogmasktable_density = r_refdef.fog_density;
507
508         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
509         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510         {
511                 d = (x * r - r_refdef.fogmasktable_start);
512                 if(developer_extra.integer)
513                         Con_DPrintf("%f ", d);
514                 d = max(0, d);
515                 if (r_fog_exp2.integer)
516                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517                 else
518                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
519                 if(developer_extra.integer)
520                         Con_DPrintf(" : %f ", alpha);
521                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
522                 if(developer_extra.integer)
523                         Con_DPrintf(" = %f\n", alpha);
524                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
525         }
526
527         for (x = 0;x < FOGWIDTH;x++)
528         {
529                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530                 data1[x][0] = b;
531                 data1[x][1] = b;
532                 data1[x][2] = b;
533                 data1[x][3] = 255;
534                 //data2[x][0] = 255 - b;
535                 //data2[x][1] = 255 - b;
536                 //data2[x][2] = 255 - b;
537                 //data2[x][3] = 255;
538         }
539         if (r_texture_fogattenuation)
540         {
541                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543         }
544         else
545         {
546                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
547                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548         }
549 }
550
551 static void R_BuildFogHeightTexture(void)
552 {
553         unsigned char *inpixels;
554         int size;
555         int x;
556         int y;
557         int j;
558         float c[4];
559         float f;
560         inpixels = NULL;
561         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
562         if (r_refdef.fogheighttexturename[0])
563                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
564         if (!inpixels)
565         {
566                 r_refdef.fog_height_tablesize = 0;
567                 if (r_texture_fogheighttexture)
568                         R_FreeTexture(r_texture_fogheighttexture);
569                 r_texture_fogheighttexture = NULL;
570                 if (r_refdef.fog_height_table2d)
571                         Mem_Free(r_refdef.fog_height_table2d);
572                 r_refdef.fog_height_table2d = NULL;
573                 if (r_refdef.fog_height_table1d)
574                         Mem_Free(r_refdef.fog_height_table1d);
575                 r_refdef.fog_height_table1d = NULL;
576                 return;
577         }
578         size = image_width;
579         r_refdef.fog_height_tablesize = size;
580         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
581         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
582         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583         Mem_Free(inpixels);
584         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
585         // average fog color table accounting for every fog layer between a point
586         // and the camera.  (Note: attenuation is handled separately!)
587         for (y = 0;y < size;y++)
588         {
589                 for (x = 0;x < size;x++)
590                 {
591                         Vector4Clear(c);
592                         f = 0;
593                         if (x < y)
594                         {
595                                 for (j = x;j <= y;j++)
596                                 {
597                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598                                         f++;
599                                 }
600                         }
601                         else
602                         {
603                                 for (j = x;j >= y;j--)
604                                 {
605                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606                                         f++;
607                                 }
608                         }
609                         f = 1.0f / f;
610                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
613                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
614                 }
615         }
616         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
617 }
618
619 //=======================================================================================================================================================
620
621 static const char *builtinshaderstrings[] =
622 {
623 #include "shader_glsl.h"
624 0
625 };
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *sourcebasename;
639         const char *extension;
640         const char **builtinshaderstrings;
641         const char *pretext;
642         const char *name;
643         char *filename;
644         char *builtinstring;
645         int builtincrc;
646 }
647 shadermodeinfo_t;
648
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {
652         {"#define USEDIFFUSE\n", " diffuse"},
653         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654         {"#define USEVIEWTINT\n", " viewtint"},
655         {"#define USECOLORMAPPING\n", " colormapping"},
656         {"#define USESATURATION\n", " saturation"},
657         {"#define USEFOGINSIDE\n", " foginside"},
658         {"#define USEFOGOUTSIDE\n", " fogoutside"},
659         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661         {"#define USEGAMMARAMPS\n", " gammaramps"},
662         {"#define USECUBEFILTER\n", " cubefilter"},
663         {"#define USEGLOW\n", " glow"},
664         {"#define USEBLOOM\n", " bloom"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USEPOSTPROCESSING\n", " postprocessing"},
667         {"#define USEREFLECTION\n", " reflection"},
668         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
679         {"#define USETRIPPY\n", " trippy"},
680         {"#define USEDEPTHRGB\n", " depthrgb"},
681         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
682         {"#define USESKELETAL\n", " skeletal"},
683         {"#define USEOCCLUDE\n", " occlude"}
684 };
685
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
688 {
689         // SHADERLANGUAGE_GLSL
690         {
691                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
692                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
693                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
694                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
695                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
696                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
697                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
700                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
701                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
703                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
704                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
705                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707         },
708 };
709
710 struct r_glsl_permutation_s;
711 typedef struct r_glsl_permutation_s
712 {
713         /// hash lookup data
714         struct r_glsl_permutation_s *hashnext;
715         unsigned int mode;
716         dpuint64 permutation;
717
718         /// indicates if we have tried compiling this permutation already
719         qboolean compiled;
720         /// 0 if compilation failed
721         int program;
722         // texture units assigned to each detected uniform
723         int tex_Texture_First;
724         int tex_Texture_Second;
725         int tex_Texture_GammaRamps;
726         int tex_Texture_Normal;
727         int tex_Texture_Color;
728         int tex_Texture_Gloss;
729         int tex_Texture_Glow;
730         int tex_Texture_SecondaryNormal;
731         int tex_Texture_SecondaryColor;
732         int tex_Texture_SecondaryGloss;
733         int tex_Texture_SecondaryGlow;
734         int tex_Texture_Pants;
735         int tex_Texture_Shirt;
736         int tex_Texture_FogHeightTexture;
737         int tex_Texture_FogMask;
738         int tex_Texture_Lightmap;
739         int tex_Texture_Deluxemap;
740         int tex_Texture_Attenuation;
741         int tex_Texture_Cube;
742         int tex_Texture_Refraction;
743         int tex_Texture_Reflection;
744         int tex_Texture_ShadowMap2D;
745         int tex_Texture_CubeProjection;
746         int tex_Texture_ScreenNormalMap;
747         int tex_Texture_ScreenDiffuse;
748         int tex_Texture_ScreenSpecular;
749         int tex_Texture_ReflectMask;
750         int tex_Texture_ReflectCube;
751         int tex_Texture_BounceGrid;
752         /// locations of detected uniforms in program object, or -1 if not found
753         int loc_Texture_First;
754         int loc_Texture_Second;
755         int loc_Texture_GammaRamps;
756         int loc_Texture_Normal;
757         int loc_Texture_Color;
758         int loc_Texture_Gloss;
759         int loc_Texture_Glow;
760         int loc_Texture_SecondaryNormal;
761         int loc_Texture_SecondaryColor;
762         int loc_Texture_SecondaryGloss;
763         int loc_Texture_SecondaryGlow;
764         int loc_Texture_Pants;
765         int loc_Texture_Shirt;
766         int loc_Texture_FogHeightTexture;
767         int loc_Texture_FogMask;
768         int loc_Texture_Lightmap;
769         int loc_Texture_Deluxemap;
770         int loc_Texture_Attenuation;
771         int loc_Texture_Cube;
772         int loc_Texture_Refraction;
773         int loc_Texture_Reflection;
774         int loc_Texture_ShadowMap2D;
775         int loc_Texture_CubeProjection;
776         int loc_Texture_ScreenNormalMap;
777         int loc_Texture_ScreenDiffuse;
778         int loc_Texture_ScreenSpecular;
779         int loc_Texture_ReflectMask;
780         int loc_Texture_ReflectCube;
781         int loc_Texture_BounceGrid;
782         int loc_Alpha;
783         int loc_BloomBlur_Parameters;
784         int loc_ClientTime;
785         int loc_Color_Ambient;
786         int loc_Color_Diffuse;
787         int loc_Color_Specular;
788         int loc_Color_Glow;
789         int loc_Color_Pants;
790         int loc_Color_Shirt;
791         int loc_DeferredColor_Ambient;
792         int loc_DeferredColor_Diffuse;
793         int loc_DeferredColor_Specular;
794         int loc_DeferredMod_Diffuse;
795         int loc_DeferredMod_Specular;
796         int loc_DistortScaleRefractReflect;
797         int loc_EyePosition;
798         int loc_FogColor;
799         int loc_FogHeightFade;
800         int loc_FogPlane;
801         int loc_FogPlaneViewDist;
802         int loc_FogRangeRecip;
803         int loc_LightColor;
804         int loc_LightDir;
805         int loc_LightPosition;
806         int loc_OffsetMapping_ScaleSteps;
807         int loc_OffsetMapping_LodDistance;
808         int loc_OffsetMapping_Bias;
809         int loc_PixelSize;
810         int loc_ReflectColor;
811         int loc_ReflectFactor;
812         int loc_ReflectOffset;
813         int loc_RefractColor;
814         int loc_Saturation;
815         int loc_ScreenCenterRefractReflect;
816         int loc_ScreenScaleRefractReflect;
817         int loc_ScreenToDepth;
818         int loc_ShadowMap_Parameters;
819         int loc_ShadowMap_TextureScale;
820         int loc_SpecularPower;
821         int loc_Skeletal_Transform12;
822         int loc_UserVec1;
823         int loc_UserVec2;
824         int loc_UserVec3;
825         int loc_UserVec4;
826         int loc_ViewTintColor;
827         int loc_ViewToLight;
828         int loc_ModelToLight;
829         int loc_TexMatrix;
830         int loc_BackgroundTexMatrix;
831         int loc_ModelViewProjectionMatrix;
832         int loc_ModelViewMatrix;
833         int loc_PixelToScreenTexCoord;
834         int loc_ModelToReflectCube;
835         int loc_ShadowMapMatrix;
836         int loc_BloomColorSubtract;
837         int loc_NormalmapScrollBlend;
838         int loc_BounceGridMatrix;
839         int loc_BounceGridIntensity;
840         /// uniform block bindings
841         int ubibind_Skeletal_Transform12_UniformBlock;
842         /// uniform block indices
843         int ubiloc_Skeletal_Transform12_UniformBlock;
844 }
845 r_glsl_permutation_t;
846
847 #define SHADERPERMUTATION_HASHSIZE 256
848
849
850 // non-degradable "lightweight" shader parameters to keep the permutations simpler
851 // these can NOT degrade! only use for simple stuff
852 enum
853 {
854         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
855         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
856         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
857         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
860         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
861         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
862         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
863         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
864         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
865         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
866         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
867         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
868 };
869 #define SHADERSTATICPARMS_COUNT 14
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876
877 extern qboolean r_shadow_shadowmapsampler;
878 extern int r_shadow_shadowmappcf;
879 qboolean R_CompileShader_CheckStaticParms(void)
880 {
881         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
882         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
883         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884
885         // detect all
886         if (r_glsl_saturation_redcompensate.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
888         if (r_glsl_vertextextureblend_usebothalphas.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
890         if (r_shadow_glossexact.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
892         if (r_glsl_postprocess.integer)
893         {
894                 if (r_glsl_postprocess_uservec1_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
896                 if (r_glsl_postprocess_uservec2_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
898                 if (r_glsl_postprocess_uservec3_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
900                 if (r_glsl_postprocess_uservec4_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
902         }
903         if (r_fxaa.integer)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
905         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
907
908         if (r_shadow_shadowmapsampler)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
910         if (r_shadow_shadowmappcf > 1)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
912         else if (r_shadow_shadowmappcf)
913                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
914         if (r_celshading.integer)
915                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
916         if (r_celoutlines.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
918
919         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
920 }
921
922 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
923         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
924                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
925         else \
926                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
927 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
928 {
929         shaderstaticparms_count = 0;
930
931         // emit all
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
944         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
945         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
946 }
947
948 /// information about each possible shader permutation
949 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
950 /// currently selected permutation
951 r_glsl_permutation_t *r_glsl_permutation;
952 /// storage for permutations linked in the hash table
953 memexpandablearray_t r_glsl_permutationarray;
954
955 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
956 {
957         //unsigned int hashdepth = 0;
958         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
959         r_glsl_permutation_t *p;
960         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
961         {
962                 if (p->mode == mode && p->permutation == permutation)
963                 {
964                         //if (hashdepth > 10)
965                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
966                         return p;
967                 }
968                 //hashdepth++;
969         }
970         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
971         p->mode = mode;
972         p->permutation = permutation;
973         p->hashnext = r_glsl_permutationhash[mode][hashindex];
974         r_glsl_permutationhash[mode][hashindex] = p;
975         //if (hashdepth > 10)
976         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
977         return p;
978 }
979
980 static char *R_ShaderStrCat(const char **strings)
981 {
982         char *string, *s;
983         const char **p = strings;
984         const char *t;
985         size_t len = 0;
986         for (p = strings;(t = *p);p++)
987                 len += strlen(t);
988         len++;
989         s = string = (char *)Mem_Alloc(r_main_mempool, len);
990         len = 0;
991         for (p = strings;(t = *p);p++)
992         {
993                 len = strlen(t);
994                 memcpy(s, t, len);
995                 s += len;
996         }
997         *s = 0;
998         return string;
999 }
1000
1001 static char *R_ShaderStrCat(const char **strings);
1002 static void R_InitShaderModeInfo(void)
1003 {
1004         int i, language;
1005         shadermodeinfo_t *modeinfo;
1006         // 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)
1007         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1008         {
1009                 for (i = 0; i < SHADERMODE_COUNT; i++)
1010                 {
1011                         char filename[MAX_QPATH];
1012                         modeinfo = &shadermodeinfo[language][i];
1013                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1014                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1015                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1016                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1017                 }
1018         }
1019 }
1020
1021 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1022 {
1023         char *shaderstring;
1024         // if the mode has no filename we have to return the builtin string
1025         if (builtinonly || !modeinfo->filename)
1026                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1027         // note that FS_LoadFile appends a 0 byte to make it a valid string
1028         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1029         if (shaderstring)
1030         {
1031                 if (printfromdisknotice)
1032                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1033                 return shaderstring;
1034         }
1035         // fall back to builtinstring
1036         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1037 }
1038
1039 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1040 {
1041         int i;
1042         int ubibind;
1043         int sampler;
1044         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1045         char *sourcestring;
1046         char permutationname[256];
1047         int vertstrings_count = 0;
1048         int geomstrings_count = 0;
1049         int fragstrings_count = 0;
1050         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1051         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1052         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1053
1054         if (p->compiled)
1055                 return;
1056         p->compiled = true;
1057         p->program = 0;
1058
1059         permutationname[0] = 0;
1060         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1061
1062         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1063
1064         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1065         if(vid.support.glshaderversion >= 140)
1066         {
1067                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1068                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1069                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1070                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1071                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1072                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1073         }
1074         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1075         else if(vid.support.glshaderversion >= 130)
1076         {
1077                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1078                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1079                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1080                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1081                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1082                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1083         }
1084         // if we can do #version 120, we should (this adds the invariant keyword)
1085         else if(vid.support.glshaderversion >= 120)
1086         {
1087                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1088                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1089                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1090                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1091                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1092                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1093         }
1094         // GLES also adds several things from GLSL120
1095         switch(vid.renderpath)
1096         {
1097         case RENDERPATH_GLES2:
1098                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1099                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1100                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1101                 break;
1102         default:
1103                 break;
1104         }
1105
1106         // the first pretext is which type of shader to compile as
1107         // (later these will all be bound together as a program object)
1108         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1109         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1110         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1111
1112         // the second pretext is the mode (for example a light source)
1113         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1114         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1115         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1116         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1117
1118         // now add all the permutation pretexts
1119         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1120         {
1121                 if (permutation & (1ll<<i))
1122                 {
1123                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1124                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1125                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1126                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1127                 }
1128                 else
1129                 {
1130                         // keep line numbers correct
1131                         vertstrings_list[vertstrings_count++] = "\n";
1132                         geomstrings_list[geomstrings_count++] = "\n";
1133                         fragstrings_list[fragstrings_count++] = "\n";
1134                 }
1135         }
1136
1137         // add static parms
1138         R_CompileShader_AddStaticParms(mode, permutation);
1139         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1140         vertstrings_count += shaderstaticparms_count;
1141         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1142         geomstrings_count += shaderstaticparms_count;
1143         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1144         fragstrings_count += shaderstaticparms_count;
1145
1146         // now append the shader text itself
1147         vertstrings_list[vertstrings_count++] = sourcestring;
1148         geomstrings_list[geomstrings_count++] = sourcestring;
1149         fragstrings_list[fragstrings_count++] = sourcestring;
1150
1151         // we don't currently use geometry shaders for anything, so just empty the list
1152         geomstrings_count = 0;
1153
1154         // compile the shader program
1155         if (vertstrings_count + geomstrings_count + fragstrings_count)
1156                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1157         if (p->program)
1158         {
1159                 CHECKGLERROR
1160                 qglUseProgram(p->program);CHECKGLERROR
1161                 // look up all the uniform variable names we care about, so we don't
1162                 // have to look them up every time we set them
1163
1164 #if 0
1165                 // debugging aid
1166                 {
1167                         GLint activeuniformindex = 0;
1168                         GLint numactiveuniforms = 0;
1169                         char uniformname[128];
1170                         GLsizei uniformnamelength = 0;
1171                         GLint uniformsize = 0;
1172                         GLenum uniformtype = 0;
1173                         memset(uniformname, 0, sizeof(uniformname));
1174                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1175                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1176                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1177                         {
1178                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1179                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1180                         }
1181                 }
1182 #endif
1183
1184                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1185                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1186                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1187                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1188                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1189                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1190                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1191                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1192                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1193                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1194                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1195                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1196                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1197                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1198                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1199                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1200                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1201                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1202                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1203                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1204                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1205                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1206                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1207                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1208                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1209                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1210                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1211                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1212                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1213                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1214                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1215                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1216                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1217                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1218                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1219                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1220                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1221                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1222                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1223                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1224                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1225                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1226                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1227                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1228                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1229                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1230                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1231                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1232                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1233                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1234                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1235                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1236                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1237                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1238                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1239                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1240                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1241                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1242                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1243                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1244                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1245                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1246                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1247                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1248                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1249                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1250                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1251                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1252                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1253                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1254                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1255                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1256                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1257                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1258                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1259                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1260                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1261                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1262                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1263                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1264                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1265                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1266                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1267                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1268                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1269                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1270                 // initialize the samplers to refer to the texture units we use
1271                 p->tex_Texture_First = -1;
1272                 p->tex_Texture_Second = -1;
1273                 p->tex_Texture_GammaRamps = -1;
1274                 p->tex_Texture_Normal = -1;
1275                 p->tex_Texture_Color = -1;
1276                 p->tex_Texture_Gloss = -1;
1277                 p->tex_Texture_Glow = -1;
1278                 p->tex_Texture_SecondaryNormal = -1;
1279                 p->tex_Texture_SecondaryColor = -1;
1280                 p->tex_Texture_SecondaryGloss = -1;
1281                 p->tex_Texture_SecondaryGlow = -1;
1282                 p->tex_Texture_Pants = -1;
1283                 p->tex_Texture_Shirt = -1;
1284                 p->tex_Texture_FogHeightTexture = -1;
1285                 p->tex_Texture_FogMask = -1;
1286                 p->tex_Texture_Lightmap = -1;
1287                 p->tex_Texture_Deluxemap = -1;
1288                 p->tex_Texture_Attenuation = -1;
1289                 p->tex_Texture_Cube = -1;
1290                 p->tex_Texture_Refraction = -1;
1291                 p->tex_Texture_Reflection = -1;
1292                 p->tex_Texture_ShadowMap2D = -1;
1293                 p->tex_Texture_CubeProjection = -1;
1294                 p->tex_Texture_ScreenNormalMap = -1;
1295                 p->tex_Texture_ScreenDiffuse = -1;
1296                 p->tex_Texture_ScreenSpecular = -1;
1297                 p->tex_Texture_ReflectMask = -1;
1298                 p->tex_Texture_ReflectCube = -1;
1299                 p->tex_Texture_BounceGrid = -1;
1300                 // bind the texture samplers in use
1301                 sampler = 0;
1302                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1303                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1304                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1305                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1306                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1307                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1308                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1309                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1310                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1311                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1312                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1313                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1314                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1315                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1316                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1317                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1318                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1319                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1320                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1321                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1322                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1323                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1324                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1325                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1326                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1327                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1328                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1329                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1330                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1331                 // get the uniform block indices so we can bind them
1332                 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1333 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1334                 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1335 #endif
1336                 // clear the uniform block bindings
1337                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1338                 // bind the uniform blocks in use
1339                 ubibind = 0;
1340 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1341                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1342 #endif
1343                 // we're done compiling and setting up the shader, at least until it is used
1344                 CHECKGLERROR
1345                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1346         }
1347         else
1348                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1349
1350         // free the strings
1351         if (sourcestring)
1352                 Mem_Free(sourcestring);
1353 }
1354
1355 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1356 {
1357         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1358         if (r_glsl_permutation != perm)
1359         {
1360                 r_glsl_permutation = perm;
1361                 if (!r_glsl_permutation->program)
1362                 {
1363                         if (!r_glsl_permutation->compiled)
1364                         {
1365                                 Con_DPrintf("Compiling shader mode %u permutation %llx\n", mode, permutation);
1366                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1367                         }
1368                         if (!r_glsl_permutation->program)
1369                         {
1370                                 // remove features until we find a valid permutation
1371                                 int i;
1372                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1373                                 {
1374                                         // reduce i more quickly whenever it would not remove any bits
1375                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1376                                         if (!(permutation & j))
1377                                                 continue;
1378                                         permutation -= j;
1379                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1380                                         if (!r_glsl_permutation->compiled)
1381                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1382                                         if (r_glsl_permutation->program)
1383                                                 break;
1384                                 }
1385                                 if (i >= SHADERPERMUTATION_COUNT)
1386                                 {
1387                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1388                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1389                                         qglUseProgram(0);CHECKGLERROR
1390                                         return; // no bit left to clear, entire mode is broken
1391                                 }
1392                         }
1393                 }
1394                 CHECKGLERROR
1395                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1396         }
1397         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1398         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1399         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1400         CHECKGLERROR
1401 }
1402
1403 void R_GLSL_Restart_f(void)
1404 {
1405         unsigned int i, limit;
1406         switch(vid.renderpath)
1407         {
1408         case RENDERPATH_GL32:
1409         case RENDERPATH_GLES2:
1410                 {
1411                         r_glsl_permutation_t *p;
1412                         r_glsl_permutation = NULL;
1413                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1414                         for (i = 0;i < limit;i++)
1415                         {
1416                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1417                                 {
1418                                         GL_Backend_FreeProgram(p->program);
1419                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1420                                 }
1421                         }
1422                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1423                 }
1424                 break;
1425         }
1426 }
1427
1428 static void R_GLSL_DumpShader_f(void)
1429 {
1430         int i, language, mode, dupe;
1431         char *text;
1432         shadermodeinfo_t *modeinfo;
1433         qfile_t *file;
1434
1435         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1436         {
1437                 modeinfo = shadermodeinfo[language];
1438                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1439                 {
1440                         // don't dump the same file multiple times (most or all shaders come from the same file)
1441                         for (dupe = mode - 1;dupe >= 0;dupe--)
1442                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1443                                         break;
1444                         if (dupe >= 0)
1445                                 continue;
1446                         text = modeinfo[mode].builtinstring;
1447                         if (!text)
1448                                 continue;
1449                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1450                         if (file)
1451                         {
1452                                 FS_Print(file, "/* The engine may define the following macros:\n");
1453                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1454                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1455                                         FS_Print(file, modeinfo[i].pretext);
1456                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1457                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1458                                 FS_Print(file, "*/\n");
1459                                 FS_Print(file, text);
1460                                 FS_Close(file);
1461                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1462                         }
1463                         else
1464                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1465                 }
1466         }
1467 }
1468
1469 void R_SetupShader_Generic(rtexture_t *t, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1470 {
1471         dpuint64 permutation = 0;
1472         if (r_trippy.integer && !notrippy)
1473                 permutation |= SHADERPERMUTATION_TRIPPY;
1474         permutation |= SHADERPERMUTATION_VIEWTINT;
1475         if (t)
1476                 permutation |= SHADERPERMUTATION_DIFFUSE;
1477         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1478                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1479         if (suppresstexalpha)
1480                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1481         if (vid.allowalphatocoverage)
1482                 GL_AlphaToCoverage(false);
1483         switch (vid.renderpath)
1484         {
1485         case RENDERPATH_GL32:
1486         case RENDERPATH_GLES2:
1487                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1488                 if (r_glsl_permutation->tex_Texture_First >= 0)
1489                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First, t);
1490                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1491                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1492                 break;
1493         }
1494 }
1495
1496 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1497 {
1498         R_SetupShader_Generic(NULL, usegamma, notrippy, false);
1499 }
1500
1501 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1502 {
1503         dpuint64 permutation = 0;
1504         if (r_trippy.integer && !notrippy)
1505                 permutation |= SHADERPERMUTATION_TRIPPY;
1506         if (depthrgb)
1507                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1508         if (skeletal)
1509                 permutation |= SHADERPERMUTATION_SKELETAL;
1510
1511         if (vid.allowalphatocoverage)
1512                 GL_AlphaToCoverage(false);
1513         switch (vid.renderpath)
1514         {
1515         case RENDERPATH_GL32:
1516         case RENDERPATH_GLES2:
1517                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1518 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1519                 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);
1520 #endif
1521                 break;
1522         }
1523 }
1524
1525 #define BLENDFUNC_ALLOWS_COLORMOD      1
1526 #define BLENDFUNC_ALLOWS_FOG           2
1527 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
1528 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1529 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1530 static int R_BlendFuncFlags(int src, int dst)
1531 {
1532         int r = 0;
1533
1534         // a blendfunc allows colormod if:
1535         // a) it can never keep the destination pixel invariant, or
1536         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1537         // this is to prevent unintended side effects from colormod
1538
1539         // a blendfunc allows fog if:
1540         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
1541         // this is to prevent unintended side effects from fog
1542
1543         // these checks are the output of fogeval.pl
1544
1545         r |= BLENDFUNC_ALLOWS_COLORMOD;
1546         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1547         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1548         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1549         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1550         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1551         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1552         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1553         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1554         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
1555         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
1556         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1557         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1558         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1559         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1560         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1561         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1562         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1563         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1564         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1565         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
1566         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1567
1568         return r;
1569 }
1570
1571 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)
1572 {
1573         // select a permutation of the lighting shader appropriate to this
1574         // combination of texture, entity, light source, and fogging, only use the
1575         // minimum features necessary to avoid wasting rendering time in the
1576         // fragment shader on features that are not being used
1577         dpuint64 permutation = 0;
1578         unsigned int mode = 0;
1579         int blendfuncflags;
1580         texture_t *t = rsurface.texture;
1581         float m16f[16];
1582         matrix4x4_t tempmatrix;
1583         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
1584         if (r_trippy.integer && !notrippy)
1585                 permutation |= SHADERPERMUTATION_TRIPPY;
1586         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
1587                 permutation |= SHADERPERMUTATION_ALPHAKILL;
1588         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
1589                 permutation |= SHADERPERMUTATION_OCCLUDE;
1590         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
1591                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
1592         if (rsurfacepass == RSURFPASS_BACKGROUND)
1593         {
1594                 // distorted background
1595                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1596                 {
1597                         mode = SHADERMODE_WATER;
1598                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1599                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1600                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
1601                         {
1602                                 // this is the right thing to do for wateralpha
1603                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1604                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1605                         }
1606                         else
1607                         {
1608                                 // this is the right thing to do for entity alpha
1609                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1610                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1611                         }
1612                 }
1613                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
1614                 {
1615                         mode = SHADERMODE_REFRACTION;
1616                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1617                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1618                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1619                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1620                 }
1621                 else
1622                 {
1623                         mode = SHADERMODE_GENERIC;
1624                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
1625                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1626                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1627                 }
1628                 if (vid.allowalphatocoverage)
1629                         GL_AlphaToCoverage(false);
1630         }
1631         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
1632         {
1633                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1634                 {
1635                         switch(t->offsetmapping)
1636                         {
1637                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1638                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1639                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1640                         case OFFSETMAPPING_OFF: break;
1641                         }
1642                 }
1643                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1644                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1645                 // normalmap (deferred prepass), may use alpha test on diffuse
1646                 mode = SHADERMODE_DEFERREDGEOMETRY;
1647                 GL_BlendFunc(GL_ONE, GL_ZERO);
1648                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1649                 if (vid.allowalphatocoverage)
1650                         GL_AlphaToCoverage(false);
1651         }
1652         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1653         {
1654                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1655                 {
1656                         switch(t->offsetmapping)
1657                         {
1658                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1659                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1660                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1661                         case OFFSETMAPPING_OFF: break;
1662                         }
1663                 }
1664                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1665                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1666                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1667                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1668                 // light source
1669                 mode = SHADERMODE_LIGHTSOURCE;
1670                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1671                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1672                 if (VectorLength2(rtlightdiffuse) > 0)
1673                         permutation |= SHADERPERMUTATION_DIFFUSE;
1674                 if (VectorLength2(rtlightspecular) > 0)
1675                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1676                 if (r_refdef.fogenabled)
1677                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1678                 if (t->colormapping)
1679                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1680                 if (r_shadow_usingshadowmap2d)
1681                 {
1682                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1683                         if(r_shadow_shadowmapvsdct)
1684                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
1685
1686                         if (r_shadow_shadowmap2ddepthbuffer)
1687                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1688                 }
1689                 if (t->reflectmasktexture)
1690                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1691                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1692                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
1693                 if (vid.allowalphatocoverage)
1694                         GL_AlphaToCoverage(false);
1695         }
1696         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1697         {
1698                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1699                 {
1700                         switch(t->offsetmapping)
1701                         {
1702                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1703                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1704                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1705                         case OFFSETMAPPING_OFF: break;
1706                         }
1707                 }
1708                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1709                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1710                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1711                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1712                 // directional model lighting
1713                 mode = SHADERMODE_LIGHTDIRECTION;
1714                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1715                         permutation |= SHADERPERMUTATION_GLOW;
1716                 if (VectorLength2(t->render_modellight_diffuse))
1717                         permutation |= SHADERPERMUTATION_DIFFUSE;
1718                 if (VectorLength2(t->render_modellight_specular) > 0)
1719                         permutation |= SHADERPERMUTATION_SPECULAR;
1720                 if (r_refdef.fogenabled)
1721                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1722                 if (t->colormapping)
1723                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1724                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1725                 {
1726                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1727                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1728
1729                         if (r_shadow_shadowmap2ddepthbuffer)
1730                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1731                 }
1732                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1733                         permutation |= SHADERPERMUTATION_REFLECTION;
1734                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1735                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1736                 if (t->reflectmasktexture)
1737                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1738                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1739                 {
1740                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1741                         if (r_shadow_bouncegrid_state.directional)
1742                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1743                 }
1744                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1745                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1746                 // when using alphatocoverage, we don't need alphakill
1747                 if (vid.allowalphatocoverage)
1748                 {
1749                         if (r_transparent_alphatocoverage.integer)
1750                         {
1751                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1752                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1753                         }
1754                         else
1755                                 GL_AlphaToCoverage(false);
1756                 }
1757         }
1758         else
1759         {
1760                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1761                 {
1762                         switch(t->offsetmapping)
1763                         {
1764                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1765                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1766                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1767                         case OFFSETMAPPING_OFF: break;
1768                         }
1769                 }
1770                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1771                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1772                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1773                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1774                 // lightmapped wall
1775                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1776                         permutation |= SHADERPERMUTATION_GLOW;
1777                 if (r_refdef.fogenabled)
1778                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1779                 if (t->colormapping)
1780                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1781                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1782                 {
1783                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1784                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1785
1786                         if (r_shadow_shadowmap2ddepthbuffer)
1787                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1788                 }
1789                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1790                         permutation |= SHADERPERMUTATION_REFLECTION;
1791                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1792                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1793                 if (t->reflectmasktexture)
1794                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1795                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1796                 {
1797                         // deluxemapping (light direction texture)
1798                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1799                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1800                         else
1801                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1802                         permutation |= SHADERPERMUTATION_DIFFUSE;
1803                         if (VectorLength2(t->render_lightmap_specular) > 0)
1804                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1805                 }
1806                 else if (r_glsl_deluxemapping.integer >= 2)
1807                 {
1808                         // fake deluxemapping (uniform light direction in tangentspace)
1809                         if (rsurface.uselightmaptexture)
1810                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
1811                         else
1812                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
1813                         permutation |= SHADERPERMUTATION_DIFFUSE;
1814                         if (VectorLength2(t->render_lightmap_specular) > 0)
1815                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1816                 }
1817                 else if (rsurface.uselightmaptexture)
1818                 {
1819                         // ordinary lightmapping (q1bsp, q3bsp)
1820                         mode = SHADERMODE_LIGHTMAP;
1821                 }
1822                 else
1823                 {
1824                         // ordinary vertex coloring (q3bsp)
1825                         mode = SHADERMODE_VERTEXCOLOR;
1826                 }
1827                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1828                 {
1829                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1830                         if (r_shadow_bouncegrid_state.directional)
1831                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1832                 }
1833                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1834                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1835                 // when using alphatocoverage, we don't need alphakill
1836                 if (vid.allowalphatocoverage)
1837                 {
1838                         if (r_transparent_alphatocoverage.integer)
1839                         {
1840                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1841                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1842                         }
1843                         else
1844                                 GL_AlphaToCoverage(false);
1845                 }
1846         }
1847         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
1848                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
1849         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1850                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
1851         switch(vid.renderpath)
1852         {
1853         case RENDERPATH_GL32:
1854         case RENDERPATH_GLES2:
1855                 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);
1856                 RSurf_UploadBuffersForBatch();
1857                 // this has to be after RSurf_PrepareVerticesForBatch
1858                 if (rsurface.batchskeletaltransform3x4buffer)
1859                         permutation |= SHADERPERMUTATION_SKELETAL;
1860                 R_SetupShader_SetPermutationGLSL(mode, permutation);
1861 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1862                 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);
1863 #endif
1864                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
1865                 if (mode == SHADERMODE_LIGHTSOURCE)
1866                 {
1867                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
1868                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1869                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1870                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
1871                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
1872                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
1873         
1874                         // additive passes are only darkened by fog, not tinted
1875                         if (r_glsl_permutation->loc_FogColor >= 0)
1876                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1877                         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);
1878                 }
1879                 else
1880                 {
1881                         if (mode == SHADERMODE_FLATCOLOR)
1882                         {
1883                                 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]);
1884                         }
1885                         else if (mode == SHADERMODE_LIGHTDIRECTION)
1886                         {
1887                                 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]);
1888                                 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]);
1889                                 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]);
1890                                 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]);
1891                                 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]);
1892                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1893                                 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]);
1894                         }
1895                         else
1896                         {
1897                                 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]);
1898                                 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]);
1899                                 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]);
1900                                 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]);
1901                                 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]);
1902                         }
1903                         // additive passes are only darkened by fog, not tinted
1904                         if (r_glsl_permutation->loc_FogColor >= 0)
1905                         {
1906                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
1907                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1908                                 else
1909                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1910                         }
1911                         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);
1912                         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]);
1913                         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]);
1914                         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);
1915                         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);
1916                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
1917                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
1918                         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);
1919                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
1920                 }
1921                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
1922                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
1923                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
1924                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
1925                 {
1926                         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]);
1927                         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]);
1928                 }
1929                 else
1930                 {
1931                         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]);
1932                         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]);
1933                 }
1934
1935                 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]);
1936                 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));
1937                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
1938                 if (r_glsl_permutation->loc_Color_Pants >= 0)
1939                 {
1940                         if (t->pantstexture)
1941                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
1942                         else
1943                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1944                 }
1945                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1946                 {
1947                         if (t->shirttexture)
1948                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
1949                         else
1950                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1951                 }
1952                 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]);
1953                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
1954                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
1955                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
1956                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
1957                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
1958                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1959                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1960                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
1961                         );
1962                 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);
1963                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
1964                 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]);
1965                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
1966                 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);}
1967                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
1968
1969                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
1970                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
1971                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
1972                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
1973                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
1974                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
1975                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
1976                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
1977                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
1978                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
1979                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
1980                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
1981                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
1982                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
1983                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
1984                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
1985                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
1986                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
1987                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
1988                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
1989                 if (rsurfacepass == RSURFPASS_BACKGROUND)
1990                 {
1991                         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);
1992                         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);
1993                         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);
1994                 }
1995                 else
1996                 {
1997                         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);
1998                 }
1999                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2000                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2001                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2002                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2003                 {
2004                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2005                         if (rsurface.rtlight)
2006                         {
2007                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2008                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2009                         }
2010                 }
2011                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2012                 CHECKGLERROR
2013                 break;
2014         }
2015 }
2016
2017 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2018 {
2019         // select a permutation of the lighting shader appropriate to this
2020         // combination of texture, entity, light source, and fogging, only use the
2021         // minimum features necessary to avoid wasting rendering time in the
2022         // fragment shader on features that are not being used
2023         dpuint64 permutation = 0;
2024         unsigned int mode = 0;
2025         const float *lightcolorbase = rtlight->currentcolor;
2026         float ambientscale = rtlight->ambientscale;
2027         float diffusescale = rtlight->diffusescale;
2028         float specularscale = rtlight->specularscale;
2029         // this is the location of the light in view space
2030         vec3_t viewlightorigin;
2031         // this transforms from view space (camera) to light space (cubemap)
2032         matrix4x4_t viewtolight;
2033         matrix4x4_t lighttoview;
2034         float viewtolight16f[16];
2035         // light source
2036         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2037         if (rtlight->currentcubemap != r_texture_whitecube)
2038                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2039         if (diffusescale > 0)
2040                 permutation |= SHADERPERMUTATION_DIFFUSE;
2041         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2042                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2043         if (r_shadow_usingshadowmap2d)
2044         {
2045                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2046                 if (r_shadow_shadowmapvsdct)
2047                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2048
2049                 if (r_shadow_shadowmap2ddepthbuffer)
2050                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2051         }
2052         if (vid.allowalphatocoverage)
2053                 GL_AlphaToCoverage(false);
2054         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2055         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2056         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2057         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2058         switch(vid.renderpath)
2059         {
2060         case RENDERPATH_GL32:
2061         case RENDERPATH_GLES2:
2062                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2063                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2064                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2065                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
2066                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
2067                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
2068                 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]);
2069                 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]);
2070                 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);
2071                 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]);
2072                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2073
2074                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2075                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2076                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2077                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
2078                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2079                 break;
2080         }
2081 }
2082
2083 #define SKINFRAME_HASH 1024
2084
2085 typedef struct
2086 {
2087         unsigned int loadsequence; // incremented each level change
2088         memexpandablearray_t array;
2089         skinframe_t *hash[SKINFRAME_HASH];
2090 }
2091 r_skinframe_t;
2092 r_skinframe_t r_skinframe;
2093
2094 void R_SkinFrame_PrepareForPurge(void)
2095 {
2096         r_skinframe.loadsequence++;
2097         // wrap it without hitting zero
2098         if (r_skinframe.loadsequence >= 200)
2099                 r_skinframe.loadsequence = 1;
2100 }
2101
2102 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2103 {
2104         if (!skinframe)
2105                 return;
2106         // mark the skinframe as used for the purging code
2107         skinframe->loadsequence = r_skinframe.loadsequence;
2108 }
2109
2110 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
2111 {
2112         if (s == NULL)
2113                 return;
2114         if (s->merged == s->base)
2115                 s->merged = NULL;
2116         R_PurgeTexture(s->stain); s->stain = NULL;
2117         R_PurgeTexture(s->merged); s->merged = NULL;
2118         R_PurgeTexture(s->base); s->base = NULL;
2119         R_PurgeTexture(s->pants); s->pants = NULL;
2120         R_PurgeTexture(s->shirt); s->shirt = NULL;
2121         R_PurgeTexture(s->nmap); s->nmap = NULL;
2122         R_PurgeTexture(s->gloss); s->gloss = NULL;
2123         R_PurgeTexture(s->glow); s->glow = NULL;
2124         R_PurgeTexture(s->fog); s->fog = NULL;
2125         R_PurgeTexture(s->reflect); s->reflect = NULL;
2126         s->loadsequence = 0;
2127 }
2128
2129 void R_SkinFrame_Purge(void)
2130 {
2131         int i;
2132         skinframe_t *s;
2133         for (i = 0;i < SKINFRAME_HASH;i++)
2134         {
2135                 for (s = r_skinframe.hash[i];s;s = s->next)
2136                 {
2137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2138                                 R_SkinFrame_PurgeSkinFrame(s);
2139                 }
2140         }
2141 }
2142
2143 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2144         skinframe_t *item;
2145         char basename[MAX_QPATH];
2146
2147         Image_StripImageExtension(name, basename, sizeof(basename));
2148
2149         if( last == NULL ) {
2150                 int hashindex;
2151                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2152                 item = r_skinframe.hash[hashindex];
2153         } else {
2154                 item = last->next;
2155         }
2156
2157         // linearly search through the hash bucket
2158         for( ; item ; item = item->next ) {
2159                 if( !strcmp( item->basename, basename ) ) {
2160                         return item;
2161                 }
2162         }
2163         return NULL;
2164 }
2165
2166 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2167 {
2168         skinframe_t *item;
2169         int compareflags = textureflags & TEXF_IMPORTANTBITS;
2170         int hashindex;
2171         char basename[MAX_QPATH];
2172
2173         Image_StripImageExtension(name, basename, sizeof(basename));
2174
2175         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2176         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2177                 if (!strcmp(item->basename, basename) &&
2178                         item->textureflags == compareflags &&
2179                         item->comparewidth == comparewidth &&
2180                         item->compareheight == compareheight &&
2181                         item->comparecrc == comparecrc)
2182                         break;
2183
2184         if (!item)
2185         {
2186                 if (!add)
2187                         return NULL;
2188                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2189                 memset(item, 0, sizeof(*item));
2190                 strlcpy(item->basename, basename, sizeof(item->basename));
2191                 item->textureflags = compareflags;
2192                 item->comparewidth = comparewidth;
2193                 item->compareheight = compareheight;
2194                 item->comparecrc = comparecrc;
2195                 item->next = r_skinframe.hash[hashindex];
2196                 r_skinframe.hash[hashindex] = item;
2197         }
2198         else if (textureflags & TEXF_FORCE_RELOAD)
2199                 R_SkinFrame_PurgeSkinFrame(item);
2200
2201         R_SkinFrame_MarkUsed(item);
2202         return item;
2203 }
2204
2205 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2206         { \
2207                 unsigned long long avgcolor[5], wsum; \
2208                 int pix, comp, w; \
2209                 avgcolor[0] = 0; \
2210                 avgcolor[1] = 0; \
2211                 avgcolor[2] = 0; \
2212                 avgcolor[3] = 0; \
2213                 avgcolor[4] = 0; \
2214                 wsum = 0; \
2215                 for(pix = 0; pix < cnt; ++pix) \
2216                 { \
2217                         w = 0; \
2218                         for(comp = 0; comp < 3; ++comp) \
2219                                 w += getpixel; \
2220                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2221                         { \
2222                                 ++wsum; \
2223                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2224                                 w = getpixel; \
2225                                 for(comp = 0; comp < 3; ++comp) \
2226                                         avgcolor[comp] += getpixel * w; \
2227                                 avgcolor[3] += w; \
2228                         } \
2229                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2230                         avgcolor[4] += getpixel; \
2231                 } \
2232                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2233                         avgcolor[3] = 1; \
2234                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2235                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2236                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2237                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2238         }
2239
2240 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2241 {
2242         skinframe_t *skinframe;
2243
2244         if (cls.state == ca_dedicated)
2245                 return NULL;
2246
2247         // return an existing skinframe if already loaded
2248         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2249         if (skinframe && skinframe->base)
2250                 return skinframe;
2251
2252         // if the skinframe doesn't exist this will create it
2253         return R_SkinFrame_LoadExternal_SkinFrame(skinframe, name, textureflags, complain, fallbacknotexture);
2254 }
2255
2256 extern cvar_t gl_picmip;
2257 skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2258 {
2259         int j;
2260         unsigned char *pixels;
2261         unsigned char *bumppixels;
2262         unsigned char *basepixels = NULL;
2263         int basepixels_width = 0;
2264         int basepixels_height = 0;
2265         rtexture_t *ddsbase = NULL;
2266         qboolean ddshasalpha = false;
2267         float ddsavgcolor[4];
2268         char basename[MAX_QPATH];
2269         int miplevel = R_PicmipForFlags(textureflags);
2270         int savemiplevel = miplevel;
2271         int mymiplevel;
2272         char vabuf[1024];
2273
2274         if (cls.state == ca_dedicated)
2275                 return NULL;
2276
2277         Image_StripImageExtension(name, basename, sizeof(basename));
2278
2279         // check for DDS texture file first
2280         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
2281         {
2282                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
2283                 if (basepixels == NULL && fallbacknotexture)
2284                         basepixels = Image_GenerateNoTexture();
2285                 if (basepixels == NULL)
2286                         return NULL;
2287         }
2288
2289         // FIXME handle miplevel
2290
2291         if (developer_loading.integer)
2292                 Con_Printf("loading skin \"%s\"\n", name);
2293
2294         // we've got some pixels to store, so really allocate this new texture now
2295         if (!skinframe)
2296                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2297         textureflags &= ~TEXF_FORCE_RELOAD;
2298         skinframe->stain = NULL;
2299         skinframe->merged = NULL;
2300         skinframe->base = NULL;
2301         skinframe->pants = NULL;
2302         skinframe->shirt = NULL;
2303         skinframe->nmap = NULL;
2304         skinframe->gloss = NULL;
2305         skinframe->glow = NULL;
2306         skinframe->fog = NULL;
2307         skinframe->reflect = NULL;
2308         skinframe->hasalpha = false;
2309         // we could store the q2animname here too
2310
2311         if (ddsbase)
2312         {
2313                 skinframe->base = ddsbase;
2314                 skinframe->hasalpha = ddshasalpha;
2315                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
2316                 if (r_loadfog && skinframe->hasalpha)
2317                         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);
2318                 //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]);
2319         }
2320         else
2321         {
2322                 basepixels_width = image_width;
2323                 basepixels_height = image_height;
2324                 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);
2325                 if (textureflags & TEXF_ALPHA)
2326                 {
2327                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2328                         {
2329                                 if (basepixels[j] < 255)
2330                                 {
2331                                         skinframe->hasalpha = true;
2332                                         break;
2333                                 }
2334                         }
2335                         if (r_loadfog && skinframe->hasalpha)
2336                         {
2337                                 // has transparent pixels
2338                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2339                                 for (j = 0;j < image_width * image_height * 4;j += 4)
2340                                 {
2341                                         pixels[j+0] = 255;
2342                                         pixels[j+1] = 255;
2343                                         pixels[j+2] = 255;
2344                                         pixels[j+3] = basepixels[j+3];
2345                                 }
2346                                 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);
2347                                 Mem_Free(pixels);
2348                         }
2349                 }
2350                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2351 #ifndef USE_GLES2
2352                 //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]);
2353                 if (r_savedds && skinframe->base)
2354                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
2355                 if (r_savedds && skinframe->fog)
2356                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2357 #endif
2358         }
2359
2360         if (r_loaddds)
2361         {
2362                 mymiplevel = savemiplevel;
2363                 if (r_loadnormalmap)
2364                         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);
2365                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2366                 if (r_loadgloss)
2367                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2368                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2369                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2370                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2371         }
2372
2373         // _norm is the name used by tenebrae and has been adopted as standard
2374         if (r_loadnormalmap && skinframe->nmap == NULL)
2375         {
2376                 mymiplevel = savemiplevel;
2377                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2378                 {
2379                         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);
2380                         Mem_Free(pixels);
2381                         pixels = NULL;
2382                 }
2383                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2384                 {
2385                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2386                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2387                         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);
2388                         Mem_Free(pixels);
2389                         Mem_Free(bumppixels);
2390                 }
2391                 else if (r_shadow_bumpscale_basetexture.value > 0)
2392                 {
2393                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2394                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2395                         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);
2396                         Mem_Free(pixels);
2397                 }
2398 #ifndef USE_GLES2
2399                 if (r_savedds && skinframe->nmap)
2400                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2401 #endif
2402         }
2403
2404         // _luma is supported only for tenebrae compatibility
2405         // _glow is the preferred name
2406         mymiplevel = savemiplevel;
2407         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))))
2408         {
2409                 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);
2410 #ifndef USE_GLES2
2411                 if (r_savedds && skinframe->glow)
2412                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2413 #endif
2414                 Mem_Free(pixels);pixels = NULL;
2415         }
2416
2417         mymiplevel = savemiplevel;
2418         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
2419         {
2420                 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);
2421 #ifndef USE_GLES2
2422                 if (r_savedds && skinframe->gloss)
2423                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2424 #endif
2425                 Mem_Free(pixels);
2426                 pixels = NULL;
2427         }
2428
2429         mymiplevel = savemiplevel;
2430         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
2431         {
2432                 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);
2433 #ifndef USE_GLES2
2434                 if (r_savedds && skinframe->pants)
2435                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2436 #endif
2437                 Mem_Free(pixels);
2438                 pixels = NULL;
2439         }
2440
2441         mymiplevel = savemiplevel;
2442         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
2443         {
2444                 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);
2445 #ifndef USE_GLES2
2446                 if (r_savedds && skinframe->shirt)
2447                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2448 #endif
2449                 Mem_Free(pixels);
2450                 pixels = NULL;
2451         }
2452
2453         mymiplevel = savemiplevel;
2454         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
2455         {
2456                 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);
2457 #ifndef USE_GLES2
2458                 if (r_savedds && skinframe->reflect)
2459                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2460 #endif
2461                 Mem_Free(pixels);
2462                 pixels = NULL;
2463         }
2464
2465         if (basepixels)
2466                 Mem_Free(basepixels);
2467
2468         return skinframe;
2469 }
2470
2471 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)
2472 {
2473         int i;
2474         skinframe_t *skinframe;
2475         char vabuf[1024];
2476
2477         if (cls.state == ca_dedicated)
2478                 return NULL;
2479
2480         // if already loaded just return it, otherwise make a new skinframe
2481         skinframe = R_SkinFrame_Find(name, textureflags, comparewidth, compareheight, comparecrc, true);
2482         if (skinframe->base)
2483                 return skinframe;
2484         textureflags &= ~TEXF_FORCE_RELOAD;
2485
2486         skinframe->stain = NULL;
2487         skinframe->merged = NULL;
2488         skinframe->base = NULL;
2489         skinframe->pants = NULL;
2490         skinframe->shirt = NULL;
2491         skinframe->nmap = NULL;
2492         skinframe->gloss = NULL;
2493         skinframe->glow = NULL;
2494         skinframe->fog = NULL;
2495         skinframe->reflect = NULL;
2496         skinframe->hasalpha = false;
2497
2498         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2499         if (!skindata)
2500                 return NULL;
2501
2502         if (developer_loading.integer)
2503                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2504
2505         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2506         {
2507                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2508                 unsigned char *b = a + width * height * 4;
2509                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2510                 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);
2511                 Mem_Free(a);
2512         }
2513         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
2514         if (textureflags & TEXF_ALPHA)
2515         {
2516                 for (i = 3;i < width * height * 4;i += 4)
2517                 {
2518                         if (skindata[i] < 255)
2519                         {
2520                                 skinframe->hasalpha = true;
2521                                 break;
2522                         }
2523                 }
2524                 if (r_loadfog && skinframe->hasalpha)
2525                 {
2526                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2527                         memcpy(fogpixels, skindata, width * height * 4);
2528                         for (i = 0;i < width * height * 4;i += 4)
2529                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2530                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
2531                         Mem_Free(fogpixels);
2532                 }
2533         }
2534
2535         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2536         //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]);
2537
2538         return skinframe;
2539 }
2540
2541 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2542 {
2543         int i;
2544         int featuresmask;
2545         skinframe_t *skinframe;
2546
2547         if (cls.state == ca_dedicated)
2548                 return NULL;
2549
2550         // if already loaded just return it, otherwise make a new skinframe
2551         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2552         if (skinframe->base)
2553                 return skinframe;
2554         //textureflags &= ~TEXF_FORCE_RELOAD;
2555
2556         skinframe->stain = NULL;
2557         skinframe->merged = NULL;
2558         skinframe->base = NULL;
2559         skinframe->pants = NULL;
2560         skinframe->shirt = NULL;
2561         skinframe->nmap = NULL;
2562         skinframe->gloss = NULL;
2563         skinframe->glow = NULL;
2564         skinframe->fog = NULL;
2565         skinframe->reflect = NULL;
2566         skinframe->hasalpha = false;
2567
2568         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2569         if (!skindata)
2570                 return NULL;
2571
2572         if (developer_loading.integer)
2573                 Con_Printf("loading quake skin \"%s\"\n", name);
2574
2575         // 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)
2576         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
2577         memcpy(skinframe->qpixels, skindata, width*height);
2578         skinframe->qwidth = width;
2579         skinframe->qheight = height;
2580
2581         featuresmask = 0;
2582         for (i = 0;i < width * height;i++)
2583                 featuresmask |= palette_featureflags[skindata[i]];
2584
2585         skinframe->hasalpha = false;
2586         // fence textures
2587         if (name[0] == '{')
2588                 skinframe->hasalpha = true;
2589         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2590         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2591         skinframe->qgeneratemerged = true;
2592         skinframe->qgeneratebase = skinframe->qhascolormapping;
2593         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2594
2595         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2596         //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]);
2597
2598         return skinframe;
2599 }
2600
2601 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2602 {
2603         int width;
2604         int height;
2605         unsigned char *skindata;
2606         char vabuf[1024];
2607
2608         if (!skinframe->qpixels)
2609                 return;
2610
2611         if (!skinframe->qhascolormapping)
2612                 colormapped = false;
2613
2614         if (colormapped)
2615         {
2616                 if (!skinframe->qgeneratebase)
2617                         return;
2618         }
2619         else
2620         {
2621                 if (!skinframe->qgeneratemerged)
2622                         return;
2623         }
2624
2625         width = skinframe->qwidth;
2626         height = skinframe->qheight;
2627         skindata = skinframe->qpixels;
2628
2629         if (skinframe->qgeneratenmap)
2630         {
2631                 unsigned char *a, *b;
2632                 skinframe->qgeneratenmap = false;
2633                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2634                 b = a + width * height * 4;
2635                 // use either a custom palette or the quake palette
2636                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
2637                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2638                 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);
2639                 Mem_Free(a);
2640         }
2641
2642         if (skinframe->qgenerateglow)
2643         {
2644                 skinframe->qgenerateglow = false;
2645                 if (skinframe->hasalpha) // fence textures
2646                         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
2647                 else
2648                         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
2649         }
2650
2651         if (colormapped)
2652         {
2653                 skinframe->qgeneratebase = false;
2654                 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);
2655                 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);
2656                 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);
2657         }
2658         else
2659         {
2660                 skinframe->qgeneratemerged = false;
2661                 if (skinframe->hasalpha) // fence textures
2662                         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);
2663                 else
2664                         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);
2665         }
2666
2667         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2668         {
2669                 Mem_Free(skinframe->qpixels);
2670                 skinframe->qpixels = NULL;
2671         }
2672 }
2673
2674 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)
2675 {
2676         int i;
2677         skinframe_t *skinframe;
2678         char vabuf[1024];
2679
2680         if (cls.state == ca_dedicated)
2681                 return NULL;
2682
2683         // if already loaded just return it, otherwise make a new skinframe
2684         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2685         if (skinframe->base)
2686                 return skinframe;
2687         textureflags &= ~TEXF_FORCE_RELOAD;
2688
2689         skinframe->stain = NULL;
2690         skinframe->merged = NULL;
2691         skinframe->base = NULL;
2692         skinframe->pants = NULL;
2693         skinframe->shirt = NULL;
2694         skinframe->nmap = NULL;
2695         skinframe->gloss = NULL;
2696         skinframe->glow = NULL;
2697         skinframe->fog = NULL;
2698         skinframe->reflect = NULL;
2699         skinframe->hasalpha = false;
2700
2701         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2702         if (!skindata)
2703                 return NULL;
2704
2705         if (developer_loading.integer)
2706                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2707
2708         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
2709         if ((textureflags & TEXF_ALPHA) && alphapalette)
2710         {
2711                 for (i = 0;i < width * height;i++)
2712                 {
2713                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2714                         {
2715                                 skinframe->hasalpha = true;
2716                                 break;
2717                         }
2718                 }
2719                 if (r_loadfog && skinframe->hasalpha)
2720                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
2721         }
2722
2723         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2724         //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]);
2725
2726         return skinframe;
2727 }
2728
2729 skinframe_t *R_SkinFrame_LoadMissing(void)
2730 {
2731         skinframe_t *skinframe;
2732
2733         if (cls.state == ca_dedicated)
2734                 return NULL;
2735
2736         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
2737         skinframe->stain = NULL;
2738         skinframe->merged = NULL;
2739         skinframe->base = NULL;
2740         skinframe->pants = NULL;
2741         skinframe->shirt = NULL;
2742         skinframe->nmap = NULL;
2743         skinframe->gloss = NULL;
2744         skinframe->glow = NULL;
2745         skinframe->fog = NULL;
2746         skinframe->reflect = NULL;
2747         skinframe->hasalpha = false;
2748
2749         skinframe->avgcolor[0] = rand() / RAND_MAX;
2750         skinframe->avgcolor[1] = rand() / RAND_MAX;
2751         skinframe->avgcolor[2] = rand() / RAND_MAX;
2752         skinframe->avgcolor[3] = 1;
2753
2754         return skinframe;
2755 }
2756
2757 skinframe_t *R_SkinFrame_LoadNoTexture(void)
2758 {
2759         int x, y;
2760         static unsigned char pix[16][16][4];
2761
2762         if (cls.state == ca_dedicated)
2763                 return NULL;
2764
2765         // this makes a light grey/dark grey checkerboard texture
2766         if (!pix[0][0][3])
2767         {
2768                 for (y = 0; y < 16; y++)
2769                 {
2770                         for (x = 0; x < 16; x++)
2771                         {
2772                                 if ((y < 8) ^ (x < 8))
2773                                 {
2774                                         pix[y][x][0] = 128;
2775                                         pix[y][x][1] = 128;
2776                                         pix[y][x][2] = 128;
2777                                         pix[y][x][3] = 255;
2778                                 }
2779                                 else
2780                                 {
2781                                         pix[y][x][0] = 64;
2782                                         pix[y][x][1] = 64;
2783                                         pix[y][x][2] = 64;
2784                                         pix[y][x][3] = 255;
2785                                 }
2786                         }
2787                 }
2788         }
2789
2790         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, 0, 0, 0, false);
2791 }
2792
2793 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
2794 {
2795         skinframe_t *skinframe;
2796         if (cls.state == ca_dedicated)
2797                 return NULL;
2798         // if already loaded just return it, otherwise make a new skinframe
2799         skinframe = R_SkinFrame_Find(name, textureflags, width, height, 0, true);
2800         if (skinframe->base)
2801                 return skinframe;
2802         textureflags &= ~TEXF_FORCE_RELOAD;
2803         skinframe->stain = NULL;
2804         skinframe->merged = NULL;
2805         skinframe->base = NULL;
2806         skinframe->pants = NULL;
2807         skinframe->shirt = NULL;
2808         skinframe->nmap = NULL;
2809         skinframe->gloss = NULL;
2810         skinframe->glow = NULL;
2811         skinframe->fog = NULL;
2812         skinframe->reflect = NULL;
2813         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
2814         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2815         if (!tex)
2816                 return NULL;
2817         if (developer_loading.integer)
2818                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2819         skinframe->base = skinframe->merged = tex;
2820         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
2821         return skinframe;
2822 }
2823
2824 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
2825 typedef struct suffixinfo_s
2826 {
2827         const char *suffix;
2828         qboolean flipx, flipy, flipdiagonal;
2829 }
2830 suffixinfo_t;
2831 static suffixinfo_t suffix[3][6] =
2832 {
2833         {
2834                 {"px",   false, false, false},
2835                 {"nx",   false, false, false},
2836                 {"py",   false, false, false},
2837                 {"ny",   false, false, false},
2838                 {"pz",   false, false, false},
2839                 {"nz",   false, false, false}
2840         },
2841         {
2842                 {"posx", false, false, false},
2843                 {"negx", false, false, false},
2844                 {"posy", false, false, false},
2845                 {"negy", false, false, false},
2846                 {"posz", false, false, false},
2847                 {"negz", false, false, false}
2848         },
2849         {
2850                 {"rt",    true, false,  true},
2851                 {"lf",   false,  true,  true},
2852                 {"ft",    true,  true, false},
2853                 {"bk",   false, false, false},
2854                 {"up",    true, false,  true},
2855                 {"dn",    true, false,  true}
2856         }
2857 };
2858
2859 static int componentorder[4] = {0, 1, 2, 3};
2860
2861 static rtexture_t *R_LoadCubemap(const char *basename)
2862 {
2863         int i, j, cubemapsize;
2864         unsigned char *cubemappixels, *image_buffer;
2865         rtexture_t *cubemaptexture;
2866         char name[256];
2867         // must start 0 so the first loadimagepixels has no requested width/height
2868         cubemapsize = 0;
2869         cubemappixels = NULL;
2870         cubemaptexture = NULL;
2871         // keep trying different suffix groups (posx, px, rt) until one loads
2872         for (j = 0;j < 3 && !cubemappixels;j++)
2873         {
2874                 // load the 6 images in the suffix group
2875                 for (i = 0;i < 6;i++)
2876                 {
2877                         // generate an image name based on the base and and suffix
2878                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
2879                         // load it
2880                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
2881                         {
2882                                 // an image loaded, make sure width and height are equal
2883                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
2884                                 {
2885                                         // if this is the first image to load successfully, allocate the cubemap memory
2886                                         if (!cubemappixels && image_width >= 1)
2887                                         {
2888                                                 cubemapsize = image_width;
2889                                                 // note this clears to black, so unavailable sides are black
2890                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
2891                                         }
2892                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
2893                                         if (cubemappixels)
2894                                                 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);
2895                                 }
2896                                 else
2897                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
2898                                 // free the image
2899                                 Mem_Free(image_buffer);
2900                         }
2901                 }
2902         }
2903         // if a cubemap loaded, upload it
2904         if (cubemappixels)
2905         {
2906                 if (developer_loading.integer)
2907                         Con_Printf("loading cubemap \"%s\"\n", basename);
2908
2909                 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);
2910                 Mem_Free(cubemappixels);
2911         }
2912         else
2913         {
2914                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
2915                 if (developer_loading.integer)
2916                 {
2917                         Con_Printf("(tried tried images ");
2918                         for (j = 0;j < 3;j++)
2919                                 for (i = 0;i < 6;i++)
2920                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
2921                         Con_Print(" and was unable to find any of them).\n");
2922                 }
2923         }
2924         return cubemaptexture;
2925 }
2926
2927 rtexture_t *R_GetCubemap(const char *basename)
2928 {
2929         int i;
2930         for (i = 0;i < r_texture_numcubemaps;i++)
2931                 if (r_texture_cubemaps[i] != NULL)
2932                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
2933                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
2934         if (i >= MAX_CUBEMAPS || !r_main_mempool)
2935                 return r_texture_whitecube;
2936         r_texture_numcubemaps++;
2937         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
2938         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
2939         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
2940         return r_texture_cubemaps[i]->texture;
2941 }
2942
2943 static void R_Main_FreeViewCache(void)
2944 {
2945         if (r_refdef.viewcache.entityvisible)
2946                 Mem_Free(r_refdef.viewcache.entityvisible);
2947         if (r_refdef.viewcache.world_pvsbits)
2948                 Mem_Free(r_refdef.viewcache.world_pvsbits);
2949         if (r_refdef.viewcache.world_leafvisible)
2950                 Mem_Free(r_refdef.viewcache.world_leafvisible);
2951         if (r_refdef.viewcache.world_surfacevisible)
2952                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2953         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2954 }
2955
2956 static void R_Main_ResizeViewCache(void)
2957 {
2958         int numentities = r_refdef.scene.numentities;
2959         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2960         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2961         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2962         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2963         if (r_refdef.viewcache.maxentities < numentities)
2964         {
2965                 r_refdef.viewcache.maxentities = numentities;
2966                 if (r_refdef.viewcache.entityvisible)
2967                         Mem_Free(r_refdef.viewcache.entityvisible);
2968                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2969         }
2970         if (r_refdef.viewcache.world_numclusters != numclusters)
2971         {
2972                 r_refdef.viewcache.world_numclusters = numclusters;
2973                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2974                 if (r_refdef.viewcache.world_pvsbits)
2975                         Mem_Free(r_refdef.viewcache.world_pvsbits);
2976                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2977         }
2978         if (r_refdef.viewcache.world_numleafs != numleafs)
2979         {
2980                 r_refdef.viewcache.world_numleafs = numleafs;
2981                 if (r_refdef.viewcache.world_leafvisible)
2982                         Mem_Free(r_refdef.viewcache.world_leafvisible);
2983                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2984         }
2985         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2986         {
2987                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2988                 if (r_refdef.viewcache.world_surfacevisible)
2989                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
2990                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2991         }
2992 }
2993
2994 extern rtexture_t *loadingscreentexture;
2995 static void gl_main_start(void)
2996 {
2997         loadingscreentexture = NULL;
2998         r_texture_blanknormalmap = NULL;
2999         r_texture_white = NULL;
3000         r_texture_grey128 = NULL;
3001         r_texture_black = NULL;
3002         r_texture_whitecube = NULL;
3003         r_texture_normalizationcube = NULL;
3004         r_texture_fogattenuation = NULL;
3005         r_texture_fogheighttexture = NULL;
3006         r_texture_gammaramps = NULL;
3007         r_texture_numcubemaps = 0;
3008         r_uniformbufferalignment = 32;
3009
3010         r_loaddds = r_texture_dds_load.integer != 0;
3011         r_savedds = vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3012
3013         switch(vid.renderpath)
3014         {
3015         case RENDERPATH_GL32:
3016         case RENDERPATH_GLES2:
3017                 Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS);
3018                 Cvar_SetValueQuick(&gl_combine, 1);
3019                 Cvar_SetValueQuick(&r_glsl, 1);
3020                 r_loadnormalmap = true;
3021                 r_loadgloss = true;
3022                 r_loadfog = false;
3023 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3024                 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3025 #endif
3026                 break;
3027         }
3028
3029         R_AnimCache_Free();
3030         R_FrameData_Reset();
3031         R_BufferData_Reset();
3032
3033         r_numqueries = 0;
3034         r_maxqueries = 0;
3035         memset(r_queries, 0, sizeof(r_queries));
3036
3037         r_qwskincache = NULL;
3038         r_qwskincache_size = 0;
3039
3040         // due to caching of texture_t references, the collision cache must be reset
3041         Collision_Cache_Reset(true);
3042
3043         // set up r_skinframe loading system for textures
3044         memset(&r_skinframe, 0, sizeof(r_skinframe));
3045         r_skinframe.loadsequence = 1;
3046         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3047
3048         r_main_texturepool = R_AllocTexturePool();
3049         R_BuildBlankTextures();
3050         R_BuildNoTexture();
3051         R_BuildWhiteCube();
3052         R_BuildNormalizationCube();
3053         r_texture_fogattenuation = NULL;
3054         r_texture_fogheighttexture = NULL;
3055         r_texture_gammaramps = NULL;
3056         //r_texture_fogintensity = NULL;
3057         memset(&r_fb, 0, sizeof(r_fb));
3058         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
3059         r_glsl_permutation = NULL;
3060         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3061         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3062         memset(&r_svbsp, 0, sizeof (r_svbsp));
3063
3064         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3065         r_texture_numcubemaps = 0;
3066
3067         r_refdef.fogmasktable_density = 0;
3068
3069 #ifdef __ANDROID__
3070         // For Steelstorm Android
3071         // FIXME CACHE the program and reload
3072         // FIXME see possible combinations for SS:BR android
3073         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
3074         R_SetupShader_SetPermutationGLSL(0, 12);
3075         R_SetupShader_SetPermutationGLSL(0, 13);
3076         R_SetupShader_SetPermutationGLSL(0, 8388621);
3077         R_SetupShader_SetPermutationGLSL(3, 0);
3078         R_SetupShader_SetPermutationGLSL(3, 2048);
3079         R_SetupShader_SetPermutationGLSL(5, 0);
3080         R_SetupShader_SetPermutationGLSL(5, 2);
3081         R_SetupShader_SetPermutationGLSL(5, 2048);
3082         R_SetupShader_SetPermutationGLSL(5, 8388608);
3083         R_SetupShader_SetPermutationGLSL(11, 1);
3084         R_SetupShader_SetPermutationGLSL(11, 2049);
3085         R_SetupShader_SetPermutationGLSL(11, 8193);
3086         R_SetupShader_SetPermutationGLSL(11, 10241);
3087         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
3088 #endif
3089 }
3090
3091 static void gl_main_shutdown(void)
3092 {
3093         R_RenderTarget_FreeUnused(true);
3094         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
3095         R_AnimCache_Free();
3096         R_FrameData_Reset();
3097         R_BufferData_Reset();
3098
3099         R_Main_FreeViewCache();
3100
3101         switch(vid.renderpath)
3102         {
3103         case RENDERPATH_GL32:
3104         case RENDERPATH_GLES2:
3105 #if defined(GL_SAMPLES_PASSED) && !defined(USE_GLES2)
3106                 if (r_maxqueries)
3107                         qglDeleteQueries(r_maxqueries, r_queries);
3108 #endif
3109                 break;
3110         }
3111
3112         r_numqueries = 0;
3113         r_maxqueries = 0;
3114         memset(r_queries, 0, sizeof(r_queries));
3115
3116         r_qwskincache = NULL;
3117         r_qwskincache_size = 0;
3118
3119         // clear out the r_skinframe state
3120         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3121         memset(&r_skinframe, 0, sizeof(r_skinframe));
3122
3123         if (r_svbsp.nodes)
3124                 Mem_Free(r_svbsp.nodes);
3125         memset(&r_svbsp, 0, sizeof (r_svbsp));
3126         R_FreeTexturePool(&r_main_texturepool);
3127         loadingscreentexture = NULL;
3128         r_texture_blanknormalmap = NULL;
3129         r_texture_white = NULL;
3130         r_texture_grey128 = NULL;
3131         r_texture_black = NULL;
3132         r_texture_whitecube = NULL;
3133         r_texture_normalizationcube = NULL;
3134         r_texture_fogattenuation = NULL;
3135         r_texture_fogheighttexture = NULL;
3136         r_texture_gammaramps = NULL;
3137         r_texture_numcubemaps = 0;
3138         //r_texture_fogintensity = NULL;
3139         memset(&r_fb, 0, sizeof(r_fb));
3140         R_GLSL_Restart_f();
3141
3142         r_glsl_permutation = NULL;
3143         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3144         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3145 }
3146
3147 static void gl_main_newmap(void)
3148 {
3149         // FIXME: move this code to client
3150         char *entities, entname[MAX_QPATH];
3151         if (r_qwskincache)
3152                 Mem_Free(r_qwskincache);
3153         r_qwskincache = NULL;
3154         r_qwskincache_size = 0;
3155         if (cl.worldmodel)
3156         {
3157                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3158                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3159                 {
3160                         CL_ParseEntityLump(entities);
3161                         Mem_Free(entities);
3162                         return;
3163                 }
3164                 if (cl.worldmodel->brush.entities)
3165                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3166         }
3167         R_Main_FreeViewCache();
3168
3169         R_FrameData_Reset();
3170         R_BufferData_Reset();
3171 }
3172
3173 void GL_Main_Init(void)
3174 {
3175         int i;
3176         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3177         R_InitShaderModeInfo();
3178
3179         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3180         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3181         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3182         if (gamemode == GAME_NEHAHRA)
3183         {
3184                 Cvar_RegisterVariable (&gl_fogenable);
3185                 Cvar_RegisterVariable (&gl_fogdensity);
3186                 Cvar_RegisterVariable (&gl_fogred);
3187                 Cvar_RegisterVariable (&gl_foggreen);
3188                 Cvar_RegisterVariable (&gl_fogblue);
3189                 Cvar_RegisterVariable (&gl_fogstart);
3190                 Cvar_RegisterVariable (&gl_fogend);
3191                 Cvar_RegisterVariable (&gl_skyclip);
3192         }
3193         Cvar_RegisterVariable(&r_motionblur);
3194         Cvar_RegisterVariable(&r_damageblur);
3195         Cvar_RegisterVariable(&r_motionblur_averaging);
3196         Cvar_RegisterVariable(&r_motionblur_randomize);
3197         Cvar_RegisterVariable(&r_motionblur_minblur);
3198         Cvar_RegisterVariable(&r_motionblur_maxblur);
3199         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
3200         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
3201         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
3202         Cvar_RegisterVariable(&r_motionblur_mousefactor);
3203         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
3204         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
3205         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3206         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3207         Cvar_RegisterVariable(&r_equalize_entities_by);
3208         Cvar_RegisterVariable(&r_equalize_entities_to);
3209         Cvar_RegisterVariable(&r_depthfirst);
3210         Cvar_RegisterVariable(&r_useinfinitefarclip);
3211         Cvar_RegisterVariable(&r_farclip_base);
3212         Cvar_RegisterVariable(&r_farclip_world);
3213         Cvar_RegisterVariable(&r_nearclip);
3214         Cvar_RegisterVariable(&r_deformvertexes);
3215         Cvar_RegisterVariable(&r_transparent);
3216         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
3217         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
3218         Cvar_RegisterVariable(&r_transparent_useplanardistance);
3219         Cvar_RegisterVariable(&r_showoverdraw);
3220         Cvar_RegisterVariable(&r_showbboxes);
3221         Cvar_RegisterVariable(&r_showbboxes_client);
3222         Cvar_RegisterVariable(&r_showsurfaces);
3223         Cvar_RegisterVariable(&r_showtris);
3224         Cvar_RegisterVariable(&r_shownormals);
3225         Cvar_RegisterVariable(&r_showlighting);
3226         Cvar_RegisterVariable(&r_showcollisionbrushes);
3227         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3228         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3229         Cvar_RegisterVariable(&r_showdisabledepthtest);
3230         Cvar_RegisterVariable(&r_showspriteedges);
3231         Cvar_RegisterVariable(&r_showparticleedges);
3232         Cvar_RegisterVariable(&r_drawportals);
3233         Cvar_RegisterVariable(&r_drawentities);
3234         Cvar_RegisterVariable(&r_draw2d);
3235         Cvar_RegisterVariable(&r_drawworld);
3236         Cvar_RegisterVariable(&r_cullentities_trace);
3237         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
3238         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3239         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3240         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3241         Cvar_RegisterVariable(&r_cullentities_trace_expand);
3242         Cvar_RegisterVariable(&r_cullentities_trace_pad);
3243         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3244         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
3245         Cvar_RegisterVariable(&r_sortentities);
3246         Cvar_RegisterVariable(&r_drawviewmodel);
3247         Cvar_RegisterVariable(&r_drawexteriormodel);
3248         Cvar_RegisterVariable(&r_speeds);
3249         Cvar_RegisterVariable(&r_fullbrights);
3250         Cvar_RegisterVariable(&r_wateralpha);
3251         Cvar_RegisterVariable(&r_dynamic);
3252         Cvar_RegisterVariable(&r_fullbright_directed);
3253         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
3254         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
3255         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
3256         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
3257         Cvar_RegisterVariable(&r_fullbright);
3258         Cvar_RegisterVariable(&r_shadows);
3259         Cvar_RegisterVariable(&r_shadows_darken);
3260         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3261         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3262         Cvar_RegisterVariable(&r_shadows_throwdistance);
3263         Cvar_RegisterVariable(&r_shadows_throwdirection);
3264         Cvar_RegisterVariable(&r_shadows_focus);
3265         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
3266         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
3267         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3268         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3269         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3270         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3271         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3272         Cvar_RegisterVariable(&r_fog_exp2);
3273         Cvar_RegisterVariable(&r_fog_clear);
3274         Cvar_RegisterVariable(&r_drawfog);
3275         Cvar_RegisterVariable(&r_transparentdepthmasking);
3276         Cvar_RegisterVariable(&r_transparent_sortmindist);
3277         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
3278         Cvar_RegisterVariable(&r_transparent_sortarraysize);
3279         Cvar_RegisterVariable(&r_texture_dds_load);
3280         Cvar_RegisterVariable(&r_texture_dds_save);
3281         Cvar_RegisterVariable(&r_textureunits);
3282         Cvar_RegisterVariable(&gl_combine);
3283         Cvar_RegisterVariable(&r_usedepthtextures);
3284         Cvar_RegisterVariable(&r_viewfbo);
3285         Cvar_RegisterVariable(&r_rendertarget_debug);
3286         Cvar_RegisterVariable(&r_viewscale);
3287         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
3288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
3289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
3290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
3291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
3292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
3293         Cvar_RegisterVariable(&r_glsl);
3294         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3295         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3296         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
3297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
3299         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
3300         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
3302         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
3303         Cvar_RegisterVariable(&r_glsl_postprocess);
3304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
3309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
3310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
3311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
3312         Cvar_RegisterVariable(&r_celshading);
3313         Cvar_RegisterVariable(&r_celoutlines);
3314
3315         Cvar_RegisterVariable(&r_water);
3316         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
3317         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3318         Cvar_RegisterVariable(&r_water_clippingplanebias);
3319         Cvar_RegisterVariable(&r_water_refractdistort);
3320         Cvar_RegisterVariable(&r_water_reflectdistort);
3321         Cvar_RegisterVariable(&r_water_scissormode);
3322         Cvar_RegisterVariable(&r_water_lowquality);
3323         Cvar_RegisterVariable(&r_water_hideplayer);
3324
3325         Cvar_RegisterVariable(&r_lerpsprites);
3326         Cvar_RegisterVariable(&r_lerpmodels);
3327         Cvar_RegisterVariable(&r_lerplightstyles);
3328         Cvar_RegisterVariable(&r_waterscroll);
3329         Cvar_RegisterVariable(&r_bloom);
3330         Cvar_RegisterVariable(&r_bloom_colorscale);
3331         Cvar_RegisterVariable(&r_bloom_brighten);
3332         Cvar_RegisterVariable(&r_bloom_blur);
3333         Cvar_RegisterVariable(&r_bloom_resolution);
3334         Cvar_RegisterVariable(&r_bloom_colorexponent);
3335         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3336         Cvar_RegisterVariable(&r_bloom_scenebrightness);
3337         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3338         Cvar_RegisterVariable(&r_hdr_glowintensity);
3339         Cvar_RegisterVariable(&r_hdr_irisadaptation);
3340         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
3341         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
3342         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
3343         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
3344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
3345         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
3346         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
3347         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3348         Cvar_RegisterVariable(&developer_texturelogging);
3349         Cvar_RegisterVariable(&gl_lightmaps);
3350         Cvar_RegisterVariable(&r_test);
3351         Cvar_RegisterVariable(&r_batch_multidraw);
3352         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
3353         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
3354         Cvar_RegisterVariable(&r_glsl_skeletal);
3355         Cvar_RegisterVariable(&r_glsl_saturation);
3356         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
3357         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
3358         Cvar_RegisterVariable(&r_framedatasize);
3359         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
3360                 Cvar_RegisterVariable(&r_buffermegs[i]);
3361         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
3362         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3363                 Cvar_SetValue("r_fullbrights", 0);
3364 #ifdef DP_MOBILETOUCH
3365         // GLES devices have terrible depth precision in general, so...
3366         Cvar_SetValueQuick(&r_nearclip, 4);
3367         Cvar_SetValueQuick(&r_farclip_base, 4096);
3368         Cvar_SetValueQuick(&r_farclip_world, 0);
3369         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
3370 #endif
3371         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
3372 }
3373
3374 void Render_Init(void)
3375 {
3376         gl_backend_init();
3377         R_Textures_Init();
3378         GL_Main_Init();
3379         Font_Init();
3380         GL_Draw_Init();
3381         R_Shadow_Init();
3382         R_Sky_Init();
3383         GL_Surf_Init();
3384         Sbar_Init();
3385         R_Particles_Init();
3386         R_Explosion_Init();
3387         R_LightningBeams_Init();
3388         Mod_RenderInit();
3389 }
3390
3391 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3392 {
3393         int i;
3394         mplane_t *p;
3395         if (r_trippy.integer)
3396                 return false;
3397         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3398         {
3399                 p = r_refdef.view.frustum + i;
3400                 switch(p->signbits)
3401                 {
3402                 default:
3403                 case 0:
3404                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3405                                 return true;
3406                         break;
3407                 case 1:
3408                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3409                                 return true;
3410                         break;
3411                 case 2:
3412                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3413                                 return true;
3414                         break;
3415                 case 3:
3416                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3417                                 return true;
3418                         break;
3419                 case 4:
3420                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3421                                 return true;
3422                         break;
3423                 case 5:
3424                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3425                                 return true;
3426                         break;
3427                 case 6:
3428                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3429                                 return true;
3430                         break;
3431                 case 7:
3432                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3433                                 return true;
3434                         break;
3435                 }
3436         }
3437         return false;
3438 }
3439
3440 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3441 {
3442         int i;
3443         const mplane_t *p;
3444         if (r_trippy.integer)
3445                 return false;
3446         for (i = 0;i < numplanes;i++)
3447         {
3448                 p = planes + i;
3449                 switch(p->signbits)
3450                 {
3451                 default:
3452                 case 0:
3453                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3454                                 return true;
3455                         break;
3456                 case 1:
3457                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3458                                 return true;
3459                         break;
3460                 case 2:
3461                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3462                                 return true;
3463                         break;
3464                 case 3:
3465                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3466                                 return true;
3467                         break;
3468                 case 4:
3469                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3470                                 return true;
3471                         break;
3472                 case 5:
3473                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3474                                 return true;
3475                         break;
3476                 case 6:
3477                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3478                                 return true;
3479                         break;
3480                 case 7:
3481                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3482                                 return true;
3483                         break;
3484                 }
3485         }
3486         return false;
3487 }
3488
3489 //==================================================================================
3490
3491 // LordHavoc: this stores temporary data used within the same frame
3492
3493 typedef struct r_framedata_mem_s
3494 {
3495         struct r_framedata_mem_s *purge; // older mem block to free on next frame
3496         size_t size; // how much usable space
3497         size_t current; // how much space in use
3498         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
3499         size_t wantedsize; // how much space was allocated
3500         unsigned char *data; // start of real data (16byte aligned)
3501 }
3502 r_framedata_mem_t;
3503
3504 static r_framedata_mem_t *r_framedata_mem;
3505
3506 void R_FrameData_Reset(void)
3507 {
3508         while (r_framedata_mem)
3509         {
3510                 r_framedata_mem_t *next = r_framedata_mem->purge;
3511                 Mem_Free(r_framedata_mem);
3512                 r_framedata_mem = next;
3513         }
3514 }
3515
3516 static void R_FrameData_Resize(qboolean mustgrow)
3517 {
3518         size_t wantedsize;
3519         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3520         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
3521         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
3522         {
3523                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
3524                 newmem->wantedsize = wantedsize;
3525                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
3526                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
3527                 newmem->current = 0;
3528                 newmem->mark = 0;
3529                 newmem->purge = r_framedata_mem;
3530                 r_framedata_mem = newmem;
3531         }
3532 }
3533
3534 void R_FrameData_NewFrame(void)
3535 {
3536         R_FrameData_Resize(false);
3537         if (!r_framedata_mem)
3538                 return;
3539         // if we ran out of space on the last frame, free the old memory now
3540         while (r_framedata_mem->purge)
3541         {
3542                 // repeatedly remove the second item in the list, leaving only head
3543                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
3544                 Mem_Free(r_framedata_mem->purge);
3545                 r_framedata_mem->purge = next;
3546         }
3547         // reset the current mem pointer
3548         r_framedata_mem->current = 0;
3549         r_framedata_mem->mark = 0;
3550 }
3551
3552 void *R_FrameData_Alloc(size_t size)
3553 {
3554         void *data;
3555         float newvalue;
3556
3557         // align to 16 byte boundary - the data pointer is already aligned, so we
3558         // only need to ensure the size of every allocation is also aligned
3559         size = (size + 15) & ~15;
3560
3561         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
3562         {
3563                 // emergency - we ran out of space, allocate more memory
3564                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
3565                 newvalue = r_framedatasize.value * 2.0f;
3566                 // 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
3567                 if (sizeof(size_t) >= 8)
3568                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
3569                 else
3570                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
3571                 // this might not be a growing it, but we'll allocate another buffer every time
3572                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
3573                 R_FrameData_Resize(true);
3574         }
3575
3576         data = r_framedata_mem->data + r_framedata_mem->current;
3577         r_framedata_mem->current += size;
3578
3579         // count the usage for stats
3580         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
3581         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
3582
3583         return (void *)data;
3584 }
3585
3586 void *R_FrameData_Store(size_t size, void *data)
3587 {
3588         void *d = R_FrameData_Alloc(size);
3589         if (d && data)
3590                 memcpy(d, data, size);
3591         return d;
3592 }
3593
3594 void R_FrameData_SetMark(void)
3595 {
3596         if (!r_framedata_mem)
3597                 return;
3598         r_framedata_mem->mark = r_framedata_mem->current;
3599 }
3600
3601 void R_FrameData_ReturnToMark(void)
3602 {
3603         if (!r_framedata_mem)
3604                 return;
3605         r_framedata_mem->current = r_framedata_mem->mark;
3606 }
3607
3608 //==================================================================================
3609
3610 // avoid reusing the same buffer objects on consecutive frames
3611 #define R_BUFFERDATA_CYCLE 3
3612
3613 typedef struct r_bufferdata_buffer_s
3614 {
3615         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
3616         size_t size; // how much usable space
3617         size_t current; // how much space in use
3618         r_meshbuffer_t *buffer; // the buffer itself
3619 }
3620 r_bufferdata_buffer_t;
3621
3622 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
3623 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
3624
3625 /// frees all dynamic buffers
3626 void R_BufferData_Reset(void)
3627 {
3628         int cycle, type;
3629         r_bufferdata_buffer_t **p, *mem;
3630         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
3631         {
3632                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3633                 {
3634                         // free all buffers
3635                         p = &r_bufferdata_buffer[cycle][type];
3636                         while (*p)
3637                         {
3638                                 mem = *p;
3639                                 *p = (*p)->purge;
3640                                 if (mem->buffer)
3641                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3642                                 Mem_Free(mem);
3643                         }
3644                 }
3645         }
3646 }
3647
3648 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
3649 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
3650 {
3651         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3652         size_t size;
3653         float newvalue = r_buffermegs[type].value;
3654
3655         // increase the cvar if we have to (but only if we already have a mem)
3656         if (mustgrow && mem)
3657                 newvalue *= 2.0f;
3658         newvalue = bound(0.25f, newvalue, 256.0f);
3659         while (newvalue * 1024*1024 < minsize)
3660                 newvalue *= 2.0f;
3661
3662         // clamp the cvar to valid range
3663         newvalue = bound(0.25f, newvalue, 256.0f);
3664         if (r_buffermegs[type].value != newvalue)
3665                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
3666
3667         // calculate size in bytes
3668         size = (size_t)(newvalue * 1024*1024);
3669         size = bound(131072, size, 256*1024*1024);
3670
3671         // allocate a new buffer if the size is different (purge old one later)
3672         // or if we were told we must grow the buffer
3673         if (!mem || mem->size != size || mustgrow)
3674         {
3675                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
3676                 mem->size = size;
3677                 mem->current = 0;
3678                 if (type == R_BUFFERDATA_VERTEX)
3679                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
3680                 else if (type == R_BUFFERDATA_INDEX16)
3681                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
3682                 else if (type == R_BUFFERDATA_INDEX32)
3683                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
3684                 else if (type == R_BUFFERDATA_UNIFORM)
3685                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
3686                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
3687                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
3688         }
3689 }
3690
3691 void R_BufferData_NewFrame(void)
3692 {
3693         int type;
3694         r_bufferdata_buffer_t **p, *mem;
3695         // cycle to the next frame's buffers
3696         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
3697         // if we ran out of space on the last time we used these buffers, free the old memory now
3698         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3699         {
3700                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
3701                 {
3702                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
3703                         // free all but the head buffer, this is how we recycle obsolete
3704                         // buffers after they are no longer in use
3705                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
3706                         while (*p)
3707                         {
3708                                 mem = *p;
3709                                 *p = (*p)->purge;
3710                                 if (mem->buffer)
3711                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3712                                 Mem_Free(mem);
3713                         }
3714                         // reset the current offset
3715                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
3716                 }
3717         }
3718 }
3719
3720 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
3721 {
3722         r_bufferdata_buffer_t *mem;
3723         int offset = 0;
3724         int padsize;
3725
3726         *returnbufferoffset = 0;
3727
3728         // align size to a byte boundary appropriate for the buffer type, this
3729         // makes all allocations have aligned start offsets
3730         if (type == R_BUFFERDATA_UNIFORM)
3731                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
3732         else
3733                 padsize = (datasize + 15) & ~15;
3734
3735         // if we ran out of space in this buffer we must allocate a new one
3736         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)
3737                 R_BufferData_Resize(type, true, padsize);
3738
3739         // if the resize did not give us enough memory, fail
3740         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)
3741                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
3742
3743         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3744         offset = (int)mem->current;
3745         mem->current += padsize;
3746
3747         // upload the data to the buffer at the chosen offset
3748         if (offset == 0)
3749                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
3750         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
3751
3752         // count the usage for stats
3753         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
3754         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
3755
3756         // return the buffer offset
3757         *returnbufferoffset = offset;
3758
3759         return mem->buffer;
3760 }
3761
3762 //==================================================================================
3763
3764 // LordHavoc: animcache originally written by Echon, rewritten since then
3765
3766 /**
3767  * Animation cache prevents re-generating mesh data for an animated model
3768  * multiple times in one frame for lighting, shadowing, reflections, etc.
3769  */
3770
3771 void R_AnimCache_Free(void)
3772 {
3773 }
3774
3775 void R_AnimCache_ClearCache(void)
3776 {
3777         int i;
3778         entity_render_t *ent;
3779
3780         for (i = 0;i < r_refdef.scene.numentities;i++)
3781         {
3782                 ent = r_refdef.scene.entities[i];
3783                 ent->animcache_vertex3f = NULL;
3784                 ent->animcache_vertex3f_vertexbuffer = NULL;
3785                 ent->animcache_vertex3f_bufferoffset = 0;
3786                 ent->animcache_normal3f = NULL;
3787                 ent->animcache_normal3f_vertexbuffer = NULL;
3788                 ent->animcache_normal3f_bufferoffset = 0;
3789                 ent->animcache_svector3f = NULL;
3790                 ent->animcache_svector3f_vertexbuffer = NULL;
3791                 ent->animcache_svector3f_bufferoffset = 0;
3792                 ent->animcache_tvector3f = NULL;
3793                 ent->animcache_tvector3f_vertexbuffer = NULL;
3794                 ent->animcache_tvector3f_bufferoffset = 0;
3795                 ent->animcache_skeletaltransform3x4 = NULL;
3796                 ent->animcache_skeletaltransform3x4buffer = NULL;
3797                 ent->animcache_skeletaltransform3x4offset = 0;
3798                 ent->animcache_skeletaltransform3x4size = 0;
3799         }
3800 }
3801
3802 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3803 {
3804         dp_model_t *model = ent->model;
3805         int numvertices;
3806
3807         // see if this ent is worth caching
3808         if (!model || !model->Draw || !model->AnimateVertices)
3809                 return false;
3810         // nothing to cache if it contains no animations and has no skeleton
3811         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
3812                 return false;
3813         // see if it is already cached for gpuskeletal
3814         if (ent->animcache_skeletaltransform3x4)
3815                 return false;
3816         // see if it is already cached as a mesh
3817         if (ent->animcache_vertex3f)
3818         {
3819                 // check if we need to add normals or tangents
3820                 if (ent->animcache_normal3f)
3821                         wantnormals = false;
3822                 if (ent->animcache_svector3f)
3823                         wanttangents = false;
3824                 if (!wantnormals && !wanttangents)
3825                         return false;
3826         }
3827
3828         // check which kind of cache we need to generate
3829         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
3830         {
3831                 // cache the skeleton so the vertex shader can use it
3832                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
3833                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
3834                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
3835                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
3836                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
3837                 // note: this can fail if the buffer is at the grow limit
3838                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
3839                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
3840         }
3841         else if (ent->animcache_vertex3f)
3842         {
3843                 // mesh was already cached but we may need to add normals/tangents
3844                 // (this only happens with multiple views, reflections, cameras, etc)
3845                 if (wantnormals || wanttangents)
3846                 {
3847                         numvertices = model->surfmesh.num_vertices;
3848                         if (wantnormals)
3849                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3850                         if (wanttangents)
3851                         {
3852                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3853                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3854                         }
3855                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3856                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3857                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3858                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3859                 }
3860         }
3861         else
3862         {
3863                 // generate mesh cache
3864                 numvertices = model->surfmesh.num_vertices;
3865                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3866                 if (wantnormals)
3867                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3868                 if (wanttangents)
3869                 {
3870                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3871                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3872                 }
3873                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3874                 if (wantnormals || wanttangents)
3875                 {
3876                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3877                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3878                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3879                 }
3880                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
3881                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
3882                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
3883         }
3884         return true;
3885 }
3886
3887 void R_AnimCache_CacheVisibleEntities(void)
3888 {
3889         int i;
3890
3891         // TODO: thread this
3892         // NOTE: R_PrepareRTLights() also caches entities
3893
3894         for (i = 0;i < r_refdef.scene.numentities;i++)
3895                 if (r_refdef.viewcache.entityvisible[i])
3896                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], true, true);
3897 }
3898
3899 //==================================================================================
3900
3901 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)
3902 {
3903         int i;
3904         vec3_t eyemins, eyemaxs;
3905         vec3_t boxmins, boxmaxs;
3906         vec3_t padmins, padmaxs;
3907         vec3_t start;
3908         vec3_t end;
3909         dp_model_t *model = r_refdef.scene.worldmodel;
3910         static vec3_t positions[] = {
3911                 { 0.5f, 0.5f, 0.5f },
3912                 { 0.0f, 0.0f, 0.0f },
3913                 { 0.0f, 0.0f, 1.0f },
3914                 { 0.0f, 1.0f, 0.0f },
3915                 { 0.0f, 1.0f, 1.0f },
3916                 { 1.0f, 0.0f, 0.0f },
3917                 { 1.0f, 0.0f, 1.0f },
3918                 { 1.0f, 1.0f, 0.0f },
3919                 { 1.0f, 1.0f, 1.0f },
3920         };
3921
3922         // sample count can be set to -1 to skip this logic, for flicker-prone objects
3923         if (numsamples < 0)
3924                 return true;
3925
3926         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
3927         if (!r_refdef.view.usevieworiginculling)
3928                 return true;
3929
3930         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
3931                 return true;
3932
3933         // expand the eye box a little
3934         eyemins[0] = eye[0] - eyejitter;
3935         eyemaxs[0] = eye[0] + eyejitter;
3936         eyemins[1] = eye[1] - eyejitter;
3937         eyemaxs[1] = eye[1] + eyejitter;
3938         eyemins[2] = eye[2] - eyejitter;
3939         eyemaxs[2] = eye[2] + eyejitter;
3940         // expand the box a little
3941         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
3942         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
3943         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
3944         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
3945         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
3946         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
3947         // make an even larger box for the acceptable area
3948         padmins[0] = boxmins[0] - pad;
3949         padmaxs[0] = boxmaxs[0] + pad;
3950         padmins[1] = boxmins[1] - pad;
3951         padmaxs[1] = boxmaxs[1] + pad;
3952         padmins[2] = boxmins[2] - pad;
3953         padmaxs[2] = boxmaxs[2] + pad;
3954
3955         // return true if eye overlaps enlarged box
3956         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
3957                 return true;
3958
3959         // try specific positions in the box first - note that these can be cached
3960         if (r_cullentities_trace_entityocclusion.integer)
3961         {
3962                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
3963                 {
3964                         VectorCopy(eye, start);
3965                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
3966                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
3967                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
3968                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
3969                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
3970                         // not picky - if the trace ended anywhere in the box we're good
3971                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
3972                                 return true;
3973                 }
3974         }
3975         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
3976                 return true;
3977
3978         // try various random positions
3979         for (i = 0; i < numsamples; i++)
3980         {
3981                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
3982                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3983                 if (r_cullentities_trace_entityocclusion.integer)
3984                 {
3985                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
3986                         // not picky - if the trace ended anywhere in the box we're good
3987                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
3988                                 return true;
3989                 }
3990                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
3991                         return true;
3992         }
3993
3994         return false;
3995 }
3996
3997
3998 static void R_View_UpdateEntityVisible (void)
3999 {
4000         int i;
4001         int renderimask;
4002         int samples;
4003         entity_render_t *ent;
4004
4005         if (r_refdef.envmap || r_fb.water.hideplayer)
4006                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
4007         else if (chase_active.integer || r_fb.water.renderingscene)
4008                 renderimask = RENDER_VIEWMODEL;
4009         else
4010                 renderimask = RENDER_EXTERIORMODEL;
4011         if (!r_drawviewmodel.integer)
4012                 renderimask |= RENDER_VIEWMODEL;
4013         if (!r_drawexteriormodel.integer)
4014                 renderimask |= RENDER_EXTERIORMODEL;
4015         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4016         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4017         {
4018                 // worldmodel can check visibility
4019                 for (i = 0;i < r_refdef.scene.numentities;i++)
4020                 {
4021                         ent = r_refdef.scene.entities[i];
4022                         if (!(ent->flags & renderimask))
4023                         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)))
4024                         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))
4025                                 r_refdef.viewcache.entityvisible[i] = true;
4026                 }
4027         }
4028         else
4029         {
4030                 // no worldmodel or it can't check visibility
4031                 for (i = 0;i < r_refdef.scene.numentities;i++)
4032                 {
4033                         ent = r_refdef.scene.entities[i];
4034                         if (!(ent->flags & renderimask))
4035                         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)))
4036                                 r_refdef.viewcache.entityvisible[i] = true;
4037                 }
4038         }
4039         if (r_cullentities_trace.integer)
4040         {
4041                 for (i = 0;i < r_refdef.scene.numentities;i++)
4042                 {
4043                         if (!r_refdef.viewcache.entityvisible[i])
4044                                 continue;
4045                         ent = r_refdef.scene.entities[i];
4046                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4047                         {
4048                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
4049                                 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))
4050                                         ent->last_trace_visibility = realtime;
4051                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4052                                         r_refdef.viewcache.entityvisible[i] = 0;
4053                         }
4054                 }
4055         }
4056 }
4057
4058 /// only used if skyrendermasked, and normally returns false
4059 static int R_DrawBrushModelsSky (void)
4060 {
4061         int i, sky;
4062         entity_render_t *ent;
4063
4064         sky = false;
4065         for (i = 0;i < r_refdef.scene.numentities;i++)
4066         {
4067                 if (!r_refdef.viewcache.entityvisible[i])
4068                         continue;
4069                 ent = r_refdef.scene.entities[i];
4070                 if (!ent->model || !ent->model->DrawSky)
4071                         continue;
4072                 ent->model->DrawSky(ent);
4073                 sky = true;
4074         }
4075         return sky;
4076 }
4077
4078 static void R_DrawNoModel(entity_render_t *ent);
4079 static void R_DrawModels(void)
4080 {
4081         int i;
4082         entity_render_t *ent;
4083
4084         for (i = 0;i < r_refdef.scene.numentities;i++)
4085         {
4086                 if (!r_refdef.viewcache.entityvisible[i])
4087                         continue;
4088                 ent = r_refdef.scene.entities[i];
4089                 r_refdef.stats[r_stat_entities]++;
4090                 /*
4091                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4092                 {
4093                         vec3_t f, l, u, o;
4094                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4095                         Con_Printf("R_DrawModels\n");
4096                         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]);
4097                         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);
4098                         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);
4099                 }
4100                 */
4101                 if (ent->model && ent->model->Draw != NULL)
4102                         ent->model->Draw(ent);
4103                 else
4104                         R_DrawNoModel(ent);
4105         }
4106 }
4107
4108 static void R_DrawModelsDepth(void)
4109 {
4110         int i;
4111         entity_render_t *ent;
4112
4113         for (i = 0;i < r_refdef.scene.numentities;i++)
4114         {
4115                 if (!r_refdef.viewcache.entityvisible[i])
4116                         continue;
4117                 ent = r_refdef.scene.entities[i];
4118                 if (ent->model && ent->model->DrawDepth != NULL)
4119                         ent->model->DrawDepth(ent);
4120         }
4121 }
4122
4123 static void R_DrawModelsDebug(void)
4124 {
4125         int i;
4126         entity_render_t *ent;
4127
4128         for (i = 0;i < r_refdef.scene.numentities;i++)
4129         {
4130                 if (!r_refdef.viewcache.entityvisible[i])
4131                         continue;
4132                 ent = r_refdef.scene.entities[i];
4133                 if (ent->model && ent->model->DrawDebug != NULL)
4134                         ent->model->DrawDebug(ent);
4135         }
4136 }
4137
4138 static void R_DrawModelsAddWaterPlanes(void)
4139 {
4140         int i;
4141         entity_render_t *ent;
4142
4143         for (i = 0;i < r_refdef.scene.numentities;i++)
4144         {
4145                 if (!r_refdef.viewcache.entityvisible[i])
4146                         continue;
4147                 ent = r_refdef.scene.entities[i];
4148                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4149                         ent->model->DrawAddWaterPlanes(ent);
4150         }
4151 }
4152
4153 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}};
4154
4155 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4156 {
4157         if (r_hdr_irisadaptation.integer)
4158         {
4159                 vec3_t p;
4160                 vec3_t ambient;
4161                 vec3_t diffuse;
4162                 vec3_t diffusenormal;
4163                 vec3_t forward;
4164                 vec_t brightness = 0.0f;
4165                 vec_t goal;
4166                 vec_t current;
4167                 vec_t d;
4168                 int c;
4169                 VectorCopy(r_refdef.view.forward, forward);
4170                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
4171                 {
4172                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
4173                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
4174                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
4175                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
4176                         d = DotProduct(forward, diffusenormal);
4177                         brightness += VectorLength(ambient);
4178                         if (d > 0)
4179                                 brightness += d * VectorLength(diffuse);
4180                 }
4181                 brightness *= 1.0f / c;
4182                 brightness += 0.00001f; // make sure it's never zero
4183                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4184                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4185                 current = r_hdr_irisadaptation_value.value;
4186                 if (current < goal)
4187                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
4188                 else if (current > goal)
4189                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
4190                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4191                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4192         }
4193         else if (r_hdr_irisadaptation_value.value != 1.0f)
4194                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4195 }
4196
4197 static void R_View_SetFrustum(const int *scissor)
4198 {
4199         int i;
4200         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4201         vec3_t forward, left, up, origin, v;
4202
4203         if(scissor)
4204         {
4205                 // flipped x coordinates (because x points left here)
4206                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4207                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4208                 // non-flipped y coordinates
4209                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4210                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4211         }
4212
4213         // we can't trust r_refdef.view.forward and friends in reflected scenes
4214         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4215
4216 #if 0
4217         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4218         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4219         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4220         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4221         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4222         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4223         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4224         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4225         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4226         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4227         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4228         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4229 #endif
4230
4231 #if 0
4232         zNear = r_refdef.nearclip;
4233         nudge = 1.0 - 1.0 / (1<<23);
4234         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4235         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4236         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4237         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4238         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4239         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4240         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4241         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4242 #endif
4243
4244
4245
4246 #if 0
4247         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4248         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4249         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4250         r_refdef.view.frustum[0].dist = m[15] - m[12];
4251
4252         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4253         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4254         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4255         r_refdef.view.frustum[1].dist = m[15] + m[12];
4256
4257         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4258         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4259         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4260         r_refdef.view.frustum[2].dist = m[15] - m[13];
4261
4262         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4263         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4264         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4265         r_refdef.view.frustum[3].dist = m[15] + m[13];
4266
4267         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4268         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4269         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4270         r_refdef.view.frustum[4].dist = m[15] - m[14];
4271
4272         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4273         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4274         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4275         r_refdef.view.frustum[5].dist = m[15] + m[14];
4276 #endif
4277
4278         if (r_refdef.view.useperspective)
4279         {
4280                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4281                 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]);
4282                 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]);
4283                 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]);
4284                 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]);
4285
4286                 // then the normals from the corners relative to origin
4287                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4288                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4289                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4290                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4291
4292                 // in a NORMAL view, forward cross left == up
4293                 // in a REFLECTED view, forward cross left == down
4294                 // so our cross products above need to be adjusted for a left handed coordinate system
4295                 CrossProduct(forward, left, v);
4296                 if(DotProduct(v, up) < 0)
4297                 {
4298                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4299                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4300                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4301                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4302                 }
4303
4304                 // Leaving those out was a mistake, those were in the old code, and they
4305                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4306                 // I couldn't reproduce it after adding those normalizations. --blub
4307                 VectorNormalize(r_refdef.view.frustum[0].normal);
4308                 VectorNormalize(r_refdef.view.frustum[1].normal);
4309                 VectorNormalize(r_refdef.view.frustum[2].normal);
4310                 VectorNormalize(r_refdef.view.frustum[3].normal);
4311
4312                 // make the corners absolute
4313                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4314                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4315                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4316                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4317
4318                 // one more normal
4319                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4320
4321                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4322                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4323                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4324                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4325                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4326         }
4327         else
4328         {
4329                 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
4330                 VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
4331                 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
4332                 VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
4333                 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
4334                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
4335                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
4336                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
4337                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
4338                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
4339         }
4340         r_refdef.view.numfrustumplanes = 5;
4341
4342         if (r_refdef.view.useclipplane)
4343         {
4344                 r_refdef.view.numfrustumplanes = 6;
4345                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4346         }
4347
4348         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4349                 PlaneClassify(r_refdef.view.frustum + i);
4350
4351         // LordHavoc: note to all quake engine coders, Quake had a special case
4352         // for 90 degrees which assumed a square view (wrong), so I removed it,
4353         // Quake2 has it disabled as well.
4354
4355         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4356         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4357         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4358         //PlaneClassify(&frustum[0]);
4359
4360         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4361         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4362         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4363         //PlaneClassify(&frustum[1]);
4364
4365         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4366         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4367         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4368         //PlaneClassify(&frustum[2]);
4369
4370         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4371         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4372         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4373         //PlaneClassify(&frustum[3]);
4374
4375         // nearclip plane
4376         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4377         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4378         //PlaneClassify(&frustum[4]);
4379 }
4380
4381 static void R_View_UpdateWithScissor(const int *myscissor)
4382 {
4383         R_Main_ResizeViewCache();
4384         R_View_SetFrustum(myscissor);
4385         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4386         R_View_UpdateEntityVisible();
4387 }
4388
4389 static void R_View_Update(void)
4390 {
4391         R_Main_ResizeViewCache();
4392         R_View_SetFrustum(NULL);
4393         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4394         R_View_UpdateEntityVisible();
4395 }
4396
4397 float viewscalefpsadjusted = 1.0f;
4398
4399 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
4400 {
4401         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
4402         scale = bound(0.03125f, scale, 1.0f);
4403         *outwidth = (int)ceil(width * scale);
4404         *outheight = (int)ceil(height * scale);
4405 }
4406
4407 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4408 {
4409         const float *customclipplane = NULL;
4410         float plane[4];
4411         int /*rtwidth,*/ rtheight;
4412         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4413         {
4414                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
4415                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4416                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4417                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4418                         dist = r_refdef.view.clipplane.dist;
4419                 plane[0] = r_refdef.view.clipplane.normal[0];
4420                 plane[1] = r_refdef.view.clipplane.normal[1];
4421                 plane[2] = r_refdef.view.clipplane.normal[2];
4422                 plane[3] = -dist;
4423                 customclipplane = plane;
4424         }
4425
4426         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
4427         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
4428
4429         if (!r_refdef.view.useperspective)
4430                 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);
4431         else if (vid.stencil && r_useinfinitefarclip.integer)
4432                 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);
4433         else
4434                 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);
4435         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4436         R_SetViewport(&r_refdef.view.viewport);
4437 }
4438
4439 void R_EntityMatrix(const matrix4x4_t *matrix)
4440 {
4441         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4442         {
4443                 gl_modelmatrixchanged = false;
4444                 gl_modelmatrix = *matrix;
4445                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4446                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4447                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4448                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4449                 CHECKGLERROR
4450                 switch(vid.renderpath)
4451                 {
4452                 case RENDERPATH_GL32:
4453                 case RENDERPATH_GLES2:
4454                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4455                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4456                         break;
4457                 }
4458         }
4459 }
4460
4461 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
4462 {
4463         r_viewport_t viewport;
4464
4465         CHECKGLERROR
4466
4467         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4468         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
4469         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4470         R_SetViewport(&viewport);
4471         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4472         GL_Color(1, 1, 1, 1);
4473         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4474         GL_BlendFunc(GL_ONE, GL_ZERO);
4475         GL_ScissorTest(false);
4476         GL_DepthMask(false);
4477         GL_DepthRange(0, 1);
4478         GL_DepthTest(false);
4479         GL_DepthFunc(GL_LEQUAL);
4480         R_EntityMatrix(&identitymatrix);
4481         R_Mesh_ResetTextureState();
4482         GL_PolygonOffset(0, 0);
4483         switch(vid.renderpath)
4484         {
4485         case RENDERPATH_GL32:
4486         case RENDERPATH_GLES2:
4487                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4488                 break;
4489         }
4490         GL_CullFace(GL_NONE);
4491
4492         CHECKGLERROR
4493 }
4494
4495 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4496 {
4497         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
4498 }
4499
4500 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4501 {
4502         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
4503         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4504         GL_Color(1, 1, 1, 1);
4505         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4506         GL_BlendFunc(GL_ONE, GL_ZERO);
4507         GL_ScissorTest(true);
4508         GL_DepthMask(true);
4509         GL_DepthRange(0, 1);
4510         GL_DepthTest(true);
4511         GL_DepthFunc(GL_LEQUAL);
4512         R_EntityMatrix(&identitymatrix);
4513         R_Mesh_ResetTextureState();
4514         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4515         switch(vid.renderpath)
4516         {
4517         case RENDERPATH_GL32:
4518         case RENDERPATH_GLES2:
4519                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4520                 break;
4521         }
4522         GL_CullFace(r_refdef.view.cullface_back);
4523 }
4524
4525 /*
4526 ================
4527 R_RenderView_UpdateViewVectors
4528 ================
4529 */
4530 void R_RenderView_UpdateViewVectors(void)
4531 {
4532         // break apart the view matrix into vectors for various purposes
4533         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4534         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4535         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4536         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4537         // make an inverted copy of the view matrix for tracking sprites
4538         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4539 }
4540
4541 void R_RenderTarget_FreeUnused(qboolean force)
4542 {
4543         int i, j, end;
4544         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4545         for (i = 0; i < end; i++)
4546         {
4547                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4548                 // free resources for rendertargets that have not been used for a while
4549                 // (note: this check is run after the frame render, so any targets used
4550                 // this frame will not be affected even at low framerates)
4551                 if (r && (realtime - r->lastusetime > 0.2 || force))
4552                 {
4553                         if (r->fbo)
4554                                 R_Mesh_DestroyFramebufferObject(r->fbo);
4555                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
4556                                 if (r->colortexture[j])
4557                                         R_FreeTexture(r->colortexture[j]);
4558                         if (r->depthtexture)
4559                                 R_FreeTexture(r->depthtexture);
4560                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
4561                 }
4562         }
4563 }
4564
4565 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
4566 {
4567         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
4568         x1 = x * iw;
4569         x2 = (x + w) * iw;
4570         y1 = (th - y) * ih;
4571         y2 = (th - y - h) * ih;
4572         texcoord2f[0] = x1;
4573         texcoord2f[2] = x2;
4574         texcoord2f[4] = x2;
4575         texcoord2f[6] = x1;
4576         texcoord2f[1] = y1;
4577         texcoord2f[3] = y1;
4578         texcoord2f[5] = y2;
4579         texcoord2f[7] = y2;
4580 }
4581
4582 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)
4583 {
4584         int i, j, end;
4585         r_rendertarget_t *r = NULL;
4586         char vabuf[256];
4587         // first try to reuse an existing slot if possible
4588         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4589         for (i = 0; i < end; i++)
4590         {
4591                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4592                 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)
4593                         break;
4594         }
4595         if (i == end)
4596         {
4597                 // no unused exact match found, so we have to make one in the first unused slot
4598                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
4599                 r->texturewidth = texturewidth;
4600                 r->textureheight = textureheight;
4601                 r->colortextype[0] = colortextype0;
4602                 r->colortextype[1] = colortextype1;
4603                 r->colortextype[2] = colortextype2;
4604                 r->colortextype[3] = colortextype3;
4605                 r->depthtextype = depthtextype;
4606                 r->depthisrenderbuffer = depthisrenderbuffer;
4607                 for (j = 0; j < 4; j++)
4608                         if (r->colortextype[j])
4609                                 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);
4610                 if (r->depthtextype)
4611                 {
4612                         if (r->depthisrenderbuffer)
4613                                 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);
4614                         else
4615                                 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);
4616                 }
4617                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
4618         }
4619         r_refdef.stats[r_stat_rendertargets_used]++;
4620         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
4621         r->lastusetime = realtime;
4622         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
4623         return r;
4624 }
4625
4626 static void R_Water_StartFrame(void)
4627 {
4628         int waterwidth, waterheight;
4629
4630         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4631                 return;
4632
4633         // set waterwidth and waterheight to the water resolution that will be
4634         // used (often less than the screen resolution for faster rendering)
4635         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4636         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4637         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
4638
4639         if (!r_water.integer || r_showsurfaces.integer)
4640                 waterwidth = waterheight = 0;
4641
4642         // set up variables that will be used in shader setup
4643         r_fb.water.waterwidth = waterwidth;
4644         r_fb.water.waterheight = waterheight;
4645         r_fb.water.texturewidth = waterwidth;
4646         r_fb.water.textureheight = waterheight;
4647         r_fb.water.camerawidth = waterwidth;
4648         r_fb.water.cameraheight = waterheight;
4649         r_fb.water.screenscale[0] = 0.5f;
4650         r_fb.water.screenscale[1] = 0.5f;
4651         r_fb.water.screencenter[0] = 0.5f;
4652         r_fb.water.screencenter[1] = 0.5f;
4653         r_fb.water.enabled = waterwidth != 0;
4654
4655         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
4656         r_fb.water.numwaterplanes = 0;
4657 }
4658
4659 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
4660 {
4661         int planeindex, bestplaneindex, vertexindex;
4662         vec3_t mins, maxs, normal, center, v, n;
4663         vec_t planescore, bestplanescore;
4664         mplane_t plane;
4665         r_waterstate_waterplane_t *p;
4666         texture_t *t = R_GetCurrentTexture(surface->texture);
4667
4668         rsurface.texture = t;
4669         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
4670         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
4671         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
4672                 return;
4673         // average the vertex normals, find the surface bounds (after deformvertexes)
4674         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
4675         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
4676         VectorCopy(n, normal);
4677         VectorCopy(v, mins);
4678         VectorCopy(v, maxs);
4679         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
4680         {
4681                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
4682                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
4683                 VectorAdd(normal, n, normal);
4684                 mins[0] = min(mins[0], v[0]);
4685                 mins[1] = min(mins[1], v[1]);
4686                 mins[2] = min(mins[2], v[2]);
4687                 maxs[0] = max(maxs[0], v[0]);
4688                 maxs[1] = max(maxs[1], v[1]);
4689                 maxs[2] = max(maxs[2], v[2]);
4690         }
4691         VectorNormalize(normal);
4692         VectorMAM(0.5f, mins, 0.5f, maxs, center);
4693
4694         VectorCopy(normal, plane.normal);
4695         VectorNormalize(plane.normal);
4696         plane.dist = DotProduct(center, plane.normal);
4697         PlaneClassify(&plane);
4698         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4699         {
4700                 // skip backfaces (except if nocullface is set)
4701 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4702 //                      return;
4703                 VectorNegate(plane.normal, plane.normal);
4704                 plane.dist *= -1;
4705                 PlaneClassify(&plane);
4706         }
4707
4708
4709         // find a matching plane if there is one
4710         bestplaneindex = -1;
4711         bestplanescore = 1048576.0f;
4712         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4713         {
4714                 if(p->camera_entity == t->camera_entity)
4715                 {
4716                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
4717                         if (bestplaneindex < 0 || bestplanescore > planescore)
4718                         {
4719                                 bestplaneindex = planeindex;
4720                                 bestplanescore = planescore;
4721                         }
4722                 }
4723         }
4724         planeindex = bestplaneindex;
4725
4726         // if this surface does not fit any known plane rendered this frame, add one
4727         if (planeindex < 0 || bestplanescore > 0.001f)
4728         {
4729                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
4730                 {
4731                         // store the new plane
4732                         planeindex = r_fb.water.numwaterplanes++;
4733                         p = r_fb.water.waterplanes + planeindex;
4734                         p->plane = plane;
4735                         // clear materialflags and pvs
4736                         p->materialflags = 0;
4737                         p->pvsvalid = false;
4738                         p->camera_entity = t->camera_entity;
4739                         VectorCopy(mins, p->mins);
4740                         VectorCopy(maxs, p->maxs);
4741                 }
4742                 else
4743                 {
4744                         // We're totally screwed.
4745                         return;
4746                 }
4747         }
4748         else
4749         {
4750                 // merge mins/maxs when we're adding this surface to the plane
4751                 p = r_fb.water.waterplanes + planeindex;
4752                 p->mins[0] = min(p->mins[0], mins[0]);
4753                 p->mins[1] = min(p->mins[1], mins[1]);
4754                 p->mins[2] = min(p->mins[2], mins[2]);
4755                 p->maxs[0] = max(p->maxs[0], maxs[0]);
4756                 p->maxs[1] = max(p->maxs[1], maxs[1]);
4757                 p->maxs[2] = max(p->maxs[2], maxs[2]);
4758         }
4759         // merge this surface's materialflags into the waterplane
4760         p->materialflags |= t->currentmaterialflags;
4761         if(!(p->materialflags & MATERIALFLAG_CAMERA))
4762         {
4763                 // merge this surface's PVS into the waterplane
4764                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4765                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4766                 {
4767                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4768                         p->pvsvalid = true;
4769                 }
4770         }
4771 }
4772
4773 extern cvar_t r_drawparticles;
4774 extern cvar_t r_drawdecals;
4775
4776 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
4777 {
4778         int myscissor[4];
4779         r_refdef_view_t originalview;
4780         r_refdef_view_t myview;
4781         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;
4782         r_waterstate_waterplane_t *p;
4783         vec3_t visorigin;
4784         r_rendertarget_t *rt;
4785
4786         originalview = r_refdef.view;
4787
4788         // lowquality hack, temporarily shut down some cvars and restore afterwards
4789         qualityreduction = r_water_lowquality.integer;
4790         if (qualityreduction > 0)
4791         {
4792                 if (qualityreduction >= 1)
4793                 {
4794                         old_r_shadows = r_shadows.integer;
4795                         old_r_worldrtlight = r_shadow_realtime_world.integer;
4796                         old_r_dlight = r_shadow_realtime_dlight.integer;
4797                         Cvar_SetValueQuick(&r_shadows, 0);
4798                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
4799                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
4800                 }
4801                 if (qualityreduction >= 2)
4802                 {
4803                         old_r_dynamic = r_dynamic.integer;
4804                         old_r_particles = r_drawparticles.integer;
4805                         old_r_decals = r_drawdecals.integer;
4806                         Cvar_SetValueQuick(&r_dynamic, 0);
4807                         Cvar_SetValueQuick(&r_drawparticles, 0);
4808                         Cvar_SetValueQuick(&r_drawdecals, 0);
4809                 }
4810         }
4811
4812         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
4813         {
4814                 p->rt_reflection = NULL;
4815                 p->rt_refraction = NULL;
4816                 p->rt_camera = NULL;
4817         }
4818
4819         // render views
4820         r_refdef.view = originalview;
4821         r_refdef.view.showdebug = false;
4822         r_refdef.view.width = r_fb.water.waterwidth;
4823         r_refdef.view.height = r_fb.water.waterheight;
4824         r_refdef.view.useclipplane = true;
4825         myview = r_refdef.view;
4826         r_fb.water.renderingscene = true;
4827         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4828         {
4829                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
4830                         continue;
4831
4832                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4833                 {
4834                         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);
4835                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4836                                 goto error;
4837                         r_refdef.view = myview;
4838                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4839                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4840                         if(r_water_scissormode.integer)
4841                         {
4842                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4843                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4844                                 {
4845                                         p->rt_reflection = NULL;
4846                                         p->rt_refraction = NULL;
4847                                         p->rt_camera = NULL;
4848                                         continue;
4849                                 }
4850                         }
4851
4852                         r_refdef.view.clipplane = p->plane;
4853                         // reflected view origin may be in solid, so don't cull with it
4854                         r_refdef.view.usevieworiginculling = false;
4855                         // reverse the cullface settings for this render
4856                         r_refdef.view.cullface_front = GL_FRONT;
4857                         r_refdef.view.cullface_back = GL_BACK;
4858                         // combined pvs (based on what can be seen from each surface center)
4859                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4860                         {
4861                                 r_refdef.view.usecustompvs = true;
4862                                 if (p->pvsvalid)
4863                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4864                                 else
4865                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4866                         }
4867
4868                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
4869                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4870                         GL_ScissorTest(false);
4871                         R_ClearScreen(r_refdef.fogenabled);
4872                         GL_ScissorTest(true);
4873                         if(r_water_scissormode.integer & 2)
4874                                 R_View_UpdateWithScissor(myscissor);
4875                         else
4876                                 R_View_Update();
4877                         R_AnimCache_CacheVisibleEntities();
4878                         if(r_water_scissormode.integer & 1)
4879                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4880                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4881
4882                         r_fb.water.hideplayer = false;
4883                         p->rt_reflection = rt;
4884                 }
4885
4886                 // render the normal view scene and copy into texture
4887                 // (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)
4888                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4889                 {
4890                         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);
4891                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4892                                 goto error;
4893                         r_refdef.view = myview;
4894                         if(r_water_scissormode.integer)
4895                         {
4896                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4897                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4898                                 {
4899                                         p->rt_reflection = NULL;
4900                                         p->rt_refraction = NULL;
4901                                         p->rt_camera = NULL;
4902                                         continue;
4903                                 }
4904                         }
4905
4906                         // combined pvs (based on what can be seen from each surface center)
4907                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4908                         {
4909                                 r_refdef.view.usecustompvs = true;
4910                                 if (p->pvsvalid)
4911                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4912                                 else
4913                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4914                         }
4915
4916                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
4917
4918                         r_refdef.view.clipplane = p->plane;
4919                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4920                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4921
4922                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
4923                         {
4924                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
4925                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
4926                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
4927                                 R_RenderView_UpdateViewVectors();
4928                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
4929                                 {
4930                                         r_refdef.view.usecustompvs = true;
4931                                         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);
4932                                 }
4933                         }
4934
4935                         PlaneClassify(&r_refdef.view.clipplane);
4936
4937                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4938                         GL_ScissorTest(false);
4939                         R_ClearScreen(r_refdef.fogenabled);
4940                         GL_ScissorTest(true);
4941                         if(r_water_scissormode.integer & 2)
4942                                 R_View_UpdateWithScissor(myscissor);
4943                         else
4944                                 R_View_Update();
4945                         R_AnimCache_CacheVisibleEntities();
4946                         if(r_water_scissormode.integer & 1)
4947                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4948                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4949
4950                         r_fb.water.hideplayer = false;
4951                         p->rt_refraction = rt;
4952                 }
4953                 else if (p->materialflags & MATERIALFLAG_CAMERA)
4954                 {
4955                         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);
4956                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4957                                 goto error;
4958                         r_refdef.view = myview;
4959
4960                         r_refdef.view.clipplane = p->plane;
4961                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4962                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4963
4964                         r_refdef.view.width = r_fb.water.camerawidth;
4965                         r_refdef.view.height = r_fb.water.cameraheight;
4966                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
4967                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
4968                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
4969                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
4970
4971                         if(p->camera_entity)
4972                         {
4973                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
4974                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
4975                         }
4976
4977                         // note: all of the view is used for displaying... so
4978                         // there is no use in scissoring
4979
4980                         // reverse the cullface settings for this render
4981                         r_refdef.view.cullface_front = GL_FRONT;
4982                         r_refdef.view.cullface_back = GL_BACK;
4983                         // also reverse the view matrix
4984                         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
4985                         R_RenderView_UpdateViewVectors();
4986                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
4987                         {
4988                                 r_refdef.view.usecustompvs = true;
4989                                 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);
4990                         }
4991                         
4992                         // camera needs no clipplane
4993                         r_refdef.view.useclipplane = false;
4994                         // TODO: is the camera origin always valid?  if so we don't need to clear this
4995                         r_refdef.view.usevieworiginculling = false;
4996
4997                         PlaneClassify(&r_refdef.view.clipplane);
4998
4999                         r_fb.water.hideplayer = false;
5000
5001                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5002                         GL_ScissorTest(false);
5003                         R_ClearScreen(r_refdef.fogenabled);
5004                         GL_ScissorTest(true);
5005                         R_View_Update();
5006                         R_AnimCache_CacheVisibleEntities();
5007                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
5008
5009                         r_fb.water.hideplayer = false;
5010                         p->rt_camera = rt;
5011                 }
5012
5013         }
5014         r_fb.water.renderingscene = false;
5015         r_refdef.view = originalview;
5016         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
5017         R_View_Update();
5018         R_AnimCache_CacheVisibleEntities();
5019         goto finish;
5020 error:
5021         r_refdef.view = originalview;
5022         r_fb.water.renderingscene = false;
5023         Cvar_SetValueQuick(&r_water, 0);
5024         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5025 finish:
5026         // lowquality hack, restore cvars
5027         if (qualityreduction > 0)
5028         {
5029                 if (qualityreduction >= 1)
5030                 {
5031                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5032                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5033                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5034                 }
5035                 if (qualityreduction >= 2)
5036                 {
5037                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5038                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5039                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5040                 }
5041         }
5042 }
5043
5044 static void R_Bloom_StartFrame(void)
5045 {
5046         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5047         int viewwidth, viewheight;
5048         textype_t textype = TEXTYPE_COLORBUFFER;
5049
5050         // clear the pointers to rendertargets from last frame as they're stale
5051         r_fb.rt_screen = NULL;
5052         r_fb.rt_bloom = NULL;
5053
5054         switch (vid.renderpath)
5055         {
5056         case RENDERPATH_GL32:
5057                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5058                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5059                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5060                 break;
5061         case RENDERPATH_GLES2:
5062                 r_fb.usedepthtextures = false;
5063                 break;
5064         }
5065
5066         if (r_viewscale_fpsscaling.integer)
5067         {
5068                 double actualframetime;
5069                 double targetframetime;
5070                 double adjust;
5071                 actualframetime = r_refdef.lastdrawscreentime;
5072                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5073                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5074                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5075                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5076                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5077                 viewscalefpsadjusted += adjust;
5078                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5079         }
5080         else
5081                 viewscalefpsadjusted = 1.0f;
5082
5083         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5084
5085         // set bloomwidth and bloomheight to the bloom resolution that will be
5086         // used (often less than the screen resolution for faster rendering)
5087         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
5088         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
5089         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
5090         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
5091         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
5092
5093         // calculate desired texture sizes
5094         screentexturewidth = viewwidth;
5095         screentextureheight = viewheight;
5096         bloomtexturewidth = r_fb.bloomwidth;
5097         bloomtextureheight = r_fb.bloomheight;
5098
5099         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))
5100         {
5101                 Cvar_SetValueQuick(&r_bloom, 0);
5102                 Cvar_SetValueQuick(&r_motionblur, 0);
5103                 Cvar_SetValueQuick(&r_damageblur, 0);
5104         }
5105
5106         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
5107         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
5108         {
5109                 if (r_fb.ghosttexture)
5110                         R_FreeTexture(r_fb.ghosttexture);
5111                 r_fb.ghosttexture = NULL;
5112
5113                 r_fb.screentexturewidth = screentexturewidth;
5114                 r_fb.screentextureheight = screentextureheight;
5115                 r_fb.textype = textype;
5116
5117                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
5118                 {
5119                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
5120                                 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);
5121                         r_fb.ghosttexture_valid = false;
5122                 }
5123         }
5124
5125         if (r_bloom.integer)
5126         {
5127                 // bloom texture is a different resolution
5128                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
5129                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5130                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
5131         }
5132         else
5133                 r_fb.bloomwidth = r_fb.bloomheight = 0;
5134
5135         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5136
5137         r_refdef.view.clear = true;
5138 }
5139
5140 static void R_Bloom_MakeTexture(void)
5141 {
5142         int x, range, dir;
5143         float xoffset, yoffset, r, brighten;
5144         float colorscale = r_bloom_colorscale.value;
5145         r_viewport_t bloomviewport;
5146         r_rendertarget_t *prev, *cur;
5147         textype_t textype = r_fb.rt_screen->colortextype[0];
5148
5149         r_refdef.stats[r_stat_bloom]++;
5150
5151         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5152
5153         // scale down screen texture to the bloom texture size
5154         CHECKGLERROR
5155         prev = r_fb.rt_screen;
5156         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5157         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5158         R_SetViewport(&bloomviewport);
5159         GL_CullFace(GL_NONE);
5160         GL_DepthTest(false);
5161         GL_BlendFunc(GL_ONE, GL_ZERO);
5162         GL_Color(colorscale, colorscale, colorscale, 1);
5163         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5164         // TODO: do boxfilter scale-down in shader?
5165         R_SetupShader_Generic(prev->colortexture[0], false, true, true);
5166         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5167         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5168         // we now have a properly scaled bloom image
5169
5170         // multiply bloom image by itself as many times as desired to darken it
5171         // TODO: if people actually use this it could be done more quickly in the previous shader pass
5172         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5173         {
5174                 prev = cur;
5175                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5176                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5177                 x *= 2;
5178                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
5179                 if(x <= 2)
5180                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
5181                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
5182                 GL_Color(1,1,1,1); // no fix factor supported here
5183                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5184                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5185                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5186                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5187         }
5188         CHECKGLERROR
5189
5190         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
5191         brighten = r_bloom_brighten.value;
5192         brighten = sqrt(brighten);
5193         if(range >= 1)
5194                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5195
5196         for (dir = 0;dir < 2;dir++)
5197         {
5198                 prev = cur;
5199                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5200                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5201                 // blend on at multiple vertical offsets to achieve a vertical blur
5202                 // TODO: do offset blends using GLSL
5203                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5204                 CHECKGLERROR
5205                 GL_BlendFunc(GL_ONE, GL_ZERO);
5206                 CHECKGLERROR
5207                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5208                 CHECKGLERROR
5209                 for (x = -range;x <= range;x++)
5210                 {
5211                         if (!dir){xoffset = 0;yoffset = x;}
5212                         else {xoffset = x;yoffset = 0;}
5213                         xoffset /= (float)prev->texturewidth;
5214                         yoffset /= (float)prev->textureheight;
5215                         // compute a texcoord array with the specified x and y offset
5216                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
5217                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
5218                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
5219                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
5220                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
5221                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
5222                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
5223                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
5224                         // this r value looks like a 'dot' particle, fading sharply to
5225                         // black at the edges
5226                         // (probably not realistic but looks good enough)
5227                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5228                         //r = brighten/(range*2+1);
5229                         r = brighten / (range * 2 + 1);
5230                         if(range >= 1)
5231                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
5232                         if (r <= 0)
5233                                 continue;
5234                         CHECKGLERROR
5235                         GL_Color(r, r, r, 1);
5236                         CHECKGLERROR
5237                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
5238                         CHECKGLERROR
5239                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5240                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5241                         CHECKGLERROR
5242                         GL_BlendFunc(GL_ONE, GL_ONE);
5243                         CHECKGLERROR
5244                 }
5245         }
5246
5247         // now we have the bloom image, so keep track of it
5248         r_fb.rt_bloom = cur;
5249 }
5250
5251 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5252 {
5253         dpuint64 permutation;
5254         float uservecs[4][4];
5255         rtexture_t *viewtexture;
5256         rtexture_t *bloomtexture;
5257
5258         R_EntityMatrix(&identitymatrix);
5259
5260         if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
5261         {
5262                 // declare variables
5263                 float blur_factor, blur_mouseaccel, blur_velocity;
5264                 static float blur_average; 
5265                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
5266
5267                 // set a goal for the factoring
5268                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
5269                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
5270                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
5271                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
5272                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
5273                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
5274
5275                 // from the goal, pick an averaged value between goal and last value
5276                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
5277                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
5278
5279                 // enforce minimum amount of blur 
5280                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
5281
5282                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
5283
5284                 // calculate values into a standard alpha
5285                 cl.motionbluralpha = 1 - exp(-
5286                                 (
5287                                         (r_motionblur.value * blur_factor / 80)
5288                                         +
5289                                         (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5290                                 )
5291                                 /
5292                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5293                                 );
5294
5295                 // randomization for the blur value to combat persistent ghosting
5296                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5297                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5298
5299                 // apply the blur
5300                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5301                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
5302                 {
5303                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5304                         GL_Color(1, 1, 1, cl.motionbluralpha);
5305                         R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
5306                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
5307                         R_SetupShader_Generic(r_fb.ghosttexture, false, true, true);
5308                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5309                         r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
5310                 }
5311
5312                 // updates old view angles for next pass
5313                 VectorCopy(cl.viewangles, blur_oldangles);
5314
5315                 // copy view into the ghost texture
5316                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
5317                 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
5318                 r_fb.ghosttexture_valid = true;
5319         }
5320
5321         if (r_fb.bloomwidth)
5322         {
5323                 // make the bloom texture
5324                 R_Bloom_MakeTexture();
5325         }
5326
5327 #if _MSC_VER >= 1400
5328 #define sscanf sscanf_s
5329 #endif
5330         memset(uservecs, 0, sizeof(uservecs));
5331         if (r_glsl_postprocess_uservec1_enable.integer)
5332                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5333         if (r_glsl_postprocess_uservec2_enable.integer)
5334                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5335         if (r_glsl_postprocess_uservec3_enable.integer)
5336                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5337         if (r_glsl_postprocess_uservec4_enable.integer)
5338                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5339
5340         // render to the screen fbo
5341         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5342         GL_Color(1, 1, 1, 1);
5343         GL_BlendFunc(GL_ONE, GL_ZERO);
5344
5345         viewtexture = r_fb.rt_screen->colortexture[0];
5346         bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
5347
5348         if (r_rendertarget_debug.integer >= 0)
5349         {
5350                 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
5351                 if (rt && rt->colortexture[0])
5352                 {
5353                         viewtexture = rt->colortexture[0];
5354                         bloomtexture = NULL;
5355                 }
5356         }
5357
5358         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
5359         switch(vid.renderpath)
5360         {
5361         case RENDERPATH_GL32:
5362         case RENDERPATH_GLES2:
5363                 permutation =
5364                         (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
5365                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5366                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
5367                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5368                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5369                 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5370                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
5371                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
5372                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
5373                 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]);
5374                 if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
5375                 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]);
5376                 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]);
5377                 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]);
5378                 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]);
5379                 if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5380                 if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5381                 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);
5382                 break;
5383         }
5384         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5385         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
5386 }
5387
5388 matrix4x4_t r_waterscrollmatrix;
5389
5390 void R_UpdateFog(void)
5391 {
5392         // Nehahra fog
5393         if (gamemode == GAME_NEHAHRA)
5394         {
5395                 if (gl_fogenable.integer)
5396                 {
5397                         r_refdef.oldgl_fogenable = true;
5398                         r_refdef.fog_density = gl_fogdensity.value;
5399                         r_refdef.fog_red = gl_fogred.value;
5400                         r_refdef.fog_green = gl_foggreen.value;
5401                         r_refdef.fog_blue = gl_fogblue.value;
5402                         r_refdef.fog_alpha = 1;
5403                         r_refdef.fog_start = 0;
5404                         r_refdef.fog_end = gl_skyclip.value;
5405                         r_refdef.fog_height = 1<<30;
5406                         r_refdef.fog_fadedepth = 128;
5407                 }
5408                 else if (r_refdef.oldgl_fogenable)
5409                 {
5410                         r_refdef.oldgl_fogenable = false;
5411                         r_refdef.fog_density = 0;
5412                         r_refdef.fog_red = 0;
5413                         r_refdef.fog_green = 0;
5414                         r_refdef.fog_blue = 0;
5415                         r_refdef.fog_alpha = 0;
5416                         r_refdef.fog_start = 0;
5417                         r_refdef.fog_end = 0;
5418                         r_refdef.fog_height = 1<<30;
5419                         r_refdef.fog_fadedepth = 128;
5420                 }
5421         }
5422
5423         // fog parms
5424         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5425         r_refdef.fog_start = max(0, r_refdef.fog_start);
5426         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5427
5428         if (r_refdef.fog_density && r_drawfog.integer)
5429         {
5430                 r_refdef.fogenabled = true;
5431                 // this is the point where the fog reaches 0.9986 alpha, which we
5432                 // consider a good enough cutoff point for the texture
5433                 // (0.9986 * 256 == 255.6)
5434                 if (r_fog_exp2.integer)
5435                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5436                 else
5437                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5438                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5439                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5440                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5441                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
5442                         R_BuildFogHeightTexture();
5443                 // fog color was already set
5444                 // update the fog texture
5445                 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)
5446                         R_BuildFogTexture();
5447                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
5448                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
5449         }
5450         else
5451                 r_refdef.fogenabled = false;
5452
5453         // fog color
5454         if (r_refdef.fog_density)
5455         {
5456                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5457                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5458                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5459
5460                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5461                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5462                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5463                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5464
5465                 {
5466                         vec3_t fogvec;
5467                         VectorCopy(r_refdef.fogcolor, fogvec);
5468                         //   color.rgb *= ContrastBoost * SceneBrightness;
5469                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5470                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5471                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5472                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5473                 }
5474         }
5475 }
5476
5477 void R_UpdateVariables(void)
5478 {
5479         R_Textures_Frame();
5480
5481         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
5482
5483         r_refdef.farclip = r_farclip_base.value;
5484         if (r_refdef.scene.worldmodel)
5485                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5486         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5487
5488         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5489                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5490         r_refdef.polygonfactor = 0;
5491         r_refdef.polygonoffset = 0;
5492
5493         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5494         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5495         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
5496         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5497         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5498         if (r_refdef.scene.worldmodel)
5499         {
5500                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
5501         }
5502         if (r_showsurfaces.integer)
5503         {
5504                 r_refdef.scene.rtworld = false;
5505                 r_refdef.scene.rtworldshadows = false;
5506                 r_refdef.scene.rtdlight = false;
5507                 r_refdef.scene.rtdlightshadows = false;
5508                 r_refdef.scene.lightmapintensity = 0;
5509         }
5510
5511         r_gpuskeletal = false;
5512         switch(vid.renderpath)
5513         {
5514         case RENDERPATH_GL32:
5515                 r_gpuskeletal = r_glsl_skeletal.integer && !r_showsurfaces.integer;
5516         case RENDERPATH_GLES2:
5517                 if(!vid_gammatables_trivial)
5518                 {
5519                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5520                         {
5521                                 // build GLSL gamma texture
5522 #define RAMPWIDTH 256
5523                                 unsigned short ramp[RAMPWIDTH * 3];
5524                                 unsigned char rampbgr[RAMPWIDTH][4];
5525                                 int i;
5526
5527                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5528
5529                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5530                                 for(i = 0; i < RAMPWIDTH; ++i)
5531                                 {
5532                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5533                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5534                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5535                                         rampbgr[i][3] = 0;
5536                                 }
5537                                 if (r_texture_gammaramps)
5538                                 {
5539                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
5540                                 }
5541                                 else
5542                                 {
5543                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
5544                                 }
5545                         }
5546                 }
5547                 else
5548                 {
5549                         // remove GLSL gamma texture
5550                 }
5551                 break;
5552         }
5553 }
5554
5555 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5556 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5557 /*
5558 ================
5559 R_SelectScene
5560 ================
5561 */
5562 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5563         if( scenetype != r_currentscenetype ) {
5564                 // store the old scenetype
5565                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5566                 r_currentscenetype = scenetype;
5567                 // move in the new scene
5568                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5569         }
5570 }
5571
5572 /*
5573 ================
5574 R_GetScenePointer
5575 ================
5576 */
5577 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5578 {
5579         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5580         if( scenetype == r_currentscenetype ) {
5581                 return &r_refdef.scene;
5582         } else {
5583                 return &r_scenes_store[ scenetype ];
5584         }
5585 }
5586
5587 static int R_SortEntities_Compare(const void *ap, const void *bp)
5588 {
5589         const entity_render_t *a = *(const entity_render_t **)ap;
5590         const entity_render_t *b = *(const entity_render_t **)bp;
5591
5592         // 1. compare model
5593         if(a->model < b->model)
5594                 return -1;
5595         if(a->model > b->model)
5596                 return +1;
5597
5598         // 2. compare skin
5599         // TODO possibly calculate the REAL skinnum here first using
5600         // skinscenes?
5601         if(a->skinnum < b->skinnum)
5602                 return -1;
5603         if(a->skinnum > b->skinnum)
5604                 return +1;
5605
5606         // everything we compared is equal
5607         return 0;
5608 }
5609 static void R_SortEntities(void)
5610 {
5611         // below or equal 2 ents, sorting never gains anything
5612         if(r_refdef.scene.numentities <= 2)
5613                 return;
5614         // sort
5615         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
5616 }
5617
5618 /*
5619 ================
5620 R_RenderView
5621 ================
5622 */
5623 extern cvar_t r_shadow_bouncegrid;
5624 extern cvar_t v_isometric;
5625 extern void V_MakeViewIsometric(void);
5626 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
5627 {
5628         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
5629         int viewfbo = 0;
5630         rtexture_t *viewdepthtexture = NULL;
5631         rtexture_t *viewcolortexture = NULL;
5632         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
5633
5634         // finish any 2D rendering that was queued
5635         DrawQ_Finish();
5636
5637         if (r_timereport_active)
5638                 R_TimeReport("start");
5639         r_textureframe++; // used only by R_GetCurrentTexture
5640         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5641
5642         if(R_CompileShader_CheckStaticParms())
5643                 R_GLSL_Restart_f();
5644
5645         if (!r_drawentities.integer)
5646                 r_refdef.scene.numentities = 0;
5647         else if (r_sortentities.integer)
5648                 R_SortEntities();
5649
5650         R_AnimCache_ClearCache();
5651
5652         /* adjust for stereo display */
5653         if(R_Stereo_Active())
5654         {
5655                 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);
5656                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
5657         }
5658
5659         if (r_refdef.view.isoverlay)
5660         {
5661                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5662                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
5663                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
5664                 R_TimeReport("depthclear");
5665
5666                 r_refdef.view.showdebug = false;
5667
5668                 r_fb.water.enabled = false;
5669                 r_fb.water.numwaterplanes = 0;
5670
5671                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5672
5673                 r_refdef.view.matrix = originalmatrix;
5674
5675                 CHECKGLERROR
5676                 return;
5677         }
5678
5679         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
5680         {
5681                 r_refdef.view.matrix = originalmatrix;
5682                 return;
5683         }
5684
5685         r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
5686         if (v_isometric.integer && r_refdef.view.ismain)
5687                 V_MakeViewIsometric();
5688
5689         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
5690
5691         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
5692                 // in sRGB fallback, behave similar to true sRGB: convert this
5693                 // value from linear to sRGB
5694                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
5695
5696         R_RenderView_UpdateViewVectors();
5697
5698         R_Shadow_UpdateWorldLightSelection();
5699
5700         // this will set up r_fb.rt_screen
5701         R_Bloom_StartFrame();
5702
5703         // apply bloom brightness offset
5704         if(r_fb.rt_bloom)
5705                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
5706
5707         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
5708         if (r_fb.rt_screen)
5709         {
5710                 viewfbo = r_fb.rt_screen->fbo;
5711                 viewdepthtexture = r_fb.rt_screen->depthtexture;
5712                 viewcolortexture = r_fb.rt_screen->colortexture[0];
5713                 viewx = 0;
5714                 viewy = 0;
5715                 viewwidth = width;
5716                 viewheight = height;
5717         }
5718
5719         R_Water_StartFrame();
5720
5721         CHECKGLERROR
5722         if (r_timereport_active)
5723                 R_TimeReport("viewsetup");
5724
5725         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5726
5727         // clear the whole fbo every frame - otherwise the driver will consider
5728         // it to be an inter-frame texture and stall in multi-gpu configurations
5729         if (r_fb.rt_screen)
5730                 GL_ScissorTest(false);
5731         R_ClearScreen(r_refdef.fogenabled);
5732         if (r_timereport_active)
5733                 R_TimeReport("viewclear");
5734
5735         r_refdef.view.clear = true;
5736
5737         r_refdef.view.showdebug = true;
5738
5739         R_View_Update();
5740         if (r_timereport_active)
5741                 R_TimeReport("visibility");
5742
5743         R_AnimCache_CacheVisibleEntities();
5744         if (r_timereport_active)
5745                 R_TimeReport("animcache");
5746
5747         R_Shadow_UpdateBounceGridTexture();
5748         if (r_timereport_active && r_shadow_bouncegrid.integer)
5749                 R_TimeReport("bouncegrid");
5750
5751         r_fb.water.numwaterplanes = 0;
5752         if (r_fb.water.enabled)
5753                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5754
5755         // for the actual view render we use scissoring a fair amount, so scissor
5756         // test needs to be on
5757         if (r_fb.rt_screen)
5758                 GL_ScissorTest(true);
5759         GL_Scissor(viewx, viewy, viewwidth, viewheight);
5760         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5761         r_fb.water.numwaterplanes = 0;
5762
5763         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
5764         GL_ScissorTest(false);
5765
5766         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
5767         if (r_timereport_active)
5768                 R_TimeReport("blendview");
5769
5770         r_refdef.view.matrix = originalmatrix;
5771
5772         CHECKGLERROR
5773
5774         // go back to 2d rendering
5775         DrawQ_Start();
5776 }
5777
5778 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5779 {
5780         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5781         {
5782                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5783                 if (r_timereport_active)
5784                         R_TimeReport("waterworld");
5785         }
5786
5787         // don't let sound skip if going slow
5788         if (r_refdef.scene.extraupdate)
5789                 S_ExtraUpdate ();
5790
5791         R_DrawModelsAddWaterPlanes();
5792         if (r_timereport_active)
5793                 R_TimeReport("watermodels");
5794
5795         if (r_fb.water.numwaterplanes)
5796         {
5797                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5798                 if (r_timereport_active)
5799                         R_TimeReport("waterscenes");
5800         }
5801 }
5802
5803 extern cvar_t cl_locs_show;
5804 static void R_DrawLocs(void);
5805 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
5806 static void R_DrawModelDecals(void);
5807 extern cvar_t cl_decals_newsystem;
5808 extern qboolean r_shadow_usingdeferredprepass;
5809 extern int r_shadow_shadowmapatlas_modelshadows_size;
5810 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5811 {
5812         qboolean shadowmapping = false;
5813
5814         if (r_timereport_active)
5815                 R_TimeReport("beginscene");
5816
5817         r_refdef.stats[r_stat_renders]++;
5818
5819         R_UpdateFog();
5820
5821         // don't let sound skip if going slow
5822         if (r_refdef.scene.extraupdate)
5823                 S_ExtraUpdate ();
5824
5825         R_MeshQueue_BeginScene();
5826
5827         R_SkyStartFrame();
5828
5829         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);
5830
5831         if (r_timereport_active)
5832                 R_TimeReport("skystartframe");
5833
5834         if (cl.csqc_vidvars.drawworld)
5835         {
5836                 // don't let sound skip if going slow
5837                 if (r_refdef.scene.extraupdate)
5838                         S_ExtraUpdate ();
5839
5840                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5841                 {
5842                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5843                         if (r_timereport_active)
5844                                 R_TimeReport("worldsky");
5845                 }
5846
5847                 if (R_DrawBrushModelsSky() && r_timereport_active)
5848                         R_TimeReport("bmodelsky");
5849
5850                 if (skyrendermasked && skyrenderlater)
5851                 {
5852                         // we have to force off the water clipping plane while rendering sky
5853                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5854                         R_Sky();
5855                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5856                         if (r_timereport_active)
5857                                 R_TimeReport("sky");
5858                 }
5859         }
5860
5861         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
5862         r_shadow_viewfbo = viewfbo;
5863         r_shadow_viewdepthtexture = viewdepthtexture;
5864         r_shadow_viewcolortexture = viewcolortexture;
5865         r_shadow_viewx = viewx;
5866         r_shadow_viewy = viewy;
5867         r_shadow_viewwidth = viewwidth;
5868         r_shadow_viewheight = viewheight;
5869
5870         R_Shadow_PrepareModelShadows();
5871         R_Shadow_PrepareLights();
5872         if (r_timereport_active)
5873                 R_TimeReport("preparelights");
5874
5875         // render all the shadowmaps that will be used for this view
5876         shadowmapping = R_Shadow_ShadowMappingEnabled();
5877         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
5878         {
5879                 R_Shadow_DrawShadowMaps();
5880                 if (r_timereport_active)
5881                         R_TimeReport("shadowmaps");
5882         }
5883
5884         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
5885         if (r_shadow_usingdeferredprepass)
5886                 R_Shadow_DrawPrepass();
5887
5888         // now we begin the forward pass of the view render
5889         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5890         {
5891                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5892                 if (r_timereport_active)
5893                         R_TimeReport("worlddepth");
5894         }
5895         if (r_depthfirst.integer >= 2)
5896         {
5897                 R_DrawModelsDepth();
5898                 if (r_timereport_active)
5899                         R_TimeReport("modeldepth");
5900         }
5901
5902         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5903         {
5904                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5905                 if (r_timereport_active)
5906                         R_TimeReport("world");
5907         }
5908
5909         // don't let sound skip if going slow
5910         if (r_refdef.scene.extraupdate)
5911                 S_ExtraUpdate ();
5912
5913         R_DrawModels();
5914         if (r_timereport_active)
5915                 R_TimeReport("models");
5916
5917         // don't let sound skip if going slow
5918         if (r_refdef.scene.extraupdate)
5919                 S_ExtraUpdate ();
5920
5921         if (!r_shadow_usingdeferredprepass)
5922         {
5923                 R_Shadow_DrawLights();
5924                 if (r_timereport_active)
5925                         R_TimeReport("rtlights");
5926         }
5927
5928         // don't let sound skip if going slow
5929         if (r_refdef.scene.extraupdate)
5930                 S_ExtraUpdate ();
5931
5932         if (cl.csqc_vidvars.drawworld)
5933         {
5934                 if (cl_decals_newsystem.integer)
5935                 {
5936                         R_DrawModelDecals();
5937                         if (r_timereport_active)
5938                                 R_TimeReport("modeldecals");
5939                 }
5940                 else
5941                 {
5942                         R_DrawDecals();
5943                         if (r_timereport_active)
5944                                 R_TimeReport("decals");
5945                 }
5946
5947                 R_DrawParticles();
5948                 if (r_timereport_active)
5949                         R_TimeReport("particles");
5950
5951                 R_DrawExplosions();
5952                 if (r_timereport_active)
5953                         R_TimeReport("explosions");
5954         }
5955
5956         if (r_refdef.view.showdebug)
5957         {
5958                 if (cl_locs_show.integer)
5959                 {
5960                         R_DrawLocs();
5961                         if (r_timereport_active)
5962                                 R_TimeReport("showlocs");
5963                 }
5964
5965                 if (r_drawportals.integer)
5966                 {
5967                         R_DrawPortals();
5968                         if (r_timereport_active)
5969                                 R_TimeReport("portals");
5970                 }
5971
5972                 if (r_showbboxes_client.value > 0)
5973                 {
5974                         R_DrawEntityBBoxes(CLVM_prog);
5975                         if (r_timereport_active)
5976                                 R_TimeReport("clbboxes");
5977                 }
5978                 if (r_showbboxes.value > 0)
5979                 {
5980                         R_DrawEntityBBoxes(SVVM_prog);
5981                         if (r_timereport_active)
5982                                 R_TimeReport("svbboxes");
5983                 }
5984         }
5985
5986         if (r_transparent.integer)
5987         {
5988                 R_MeshQueue_RenderTransparent();
5989                 if (r_timereport_active)
5990                         R_TimeReport("drawtrans");
5991         }
5992
5993         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))
5994         {
5995                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5996                 if (r_timereport_active)
5997                         R_TimeReport("worlddebug");
5998                 R_DrawModelsDebug();
5999                 if (r_timereport_active)
6000                         R_TimeReport("modeldebug");
6001         }
6002
6003         if (cl.csqc_vidvars.drawworld)
6004         {
6005                 R_Shadow_DrawCoronas();
6006                 if (r_timereport_active)
6007                         R_TimeReport("coronas");
6008         }
6009
6010         // don't let sound skip if going slow
6011         if (r_refdef.scene.extraupdate)
6012                 S_ExtraUpdate ();
6013 }
6014
6015 static const unsigned short bboxelements[36] =
6016 {
6017         5, 1, 3, 5, 3, 7,
6018         6, 2, 0, 6, 0, 4,
6019         7, 3, 2, 7, 2, 6,
6020         4, 0, 1, 4, 1, 5,
6021         4, 5, 7, 4, 7, 6,
6022         1, 0, 2, 1, 2, 3,
6023 };
6024
6025 #define BBOXEDGES 13
6026 static const float bboxedges[BBOXEDGES][6] = 
6027 {
6028         // whole box
6029         { 0, 0, 0, 1, 1, 1 },
6030         // bottom edges
6031         { 0, 0, 0, 0, 1, 0 },
6032         { 0, 0, 0, 1, 0, 0 },
6033         { 0, 1, 0, 1, 1, 0 },
6034         { 1, 0, 0, 1, 1, 0 },
6035         // top edges
6036         { 0, 0, 1, 0, 1, 1 },
6037         { 0, 0, 1, 1, 0, 1 },
6038         { 0, 1, 1, 1, 1, 1 },
6039         { 1, 0, 1, 1, 1, 1 },
6040         // vertical edges
6041         { 0, 0, 0, 0, 0, 1 },
6042         { 1, 0, 0, 1, 0, 1 },
6043         { 0, 1, 0, 0, 1, 1 },
6044         { 1, 1, 0, 1, 1, 1 },
6045 };
6046
6047 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6048 {
6049         int numvertices = BBOXEDGES * 8;
6050         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
6051         int numtriangles = BBOXEDGES * 12;
6052         unsigned short elements[BBOXEDGES * 36];
6053         int i, edge;
6054         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
6055
6056         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
6057
6058         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6059         GL_DepthMask(false);
6060         GL_DepthRange(0, 1);
6061         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6062
6063         for (edge = 0; edge < BBOXEDGES; edge++)
6064         {
6065                 for (i = 0; i < 3; i++)
6066                 {
6067                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
6068                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
6069                 }
6070                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
6071                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
6072                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
6073                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
6074                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
6075                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
6076                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
6077                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
6078                 for (i = 0; i < 36; i++)
6079                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
6080         }
6081         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
6082         if (r_refdef.fogenabled)
6083         {
6084                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
6085                 {
6086                         f1 = RSurf_FogVertex(v);
6087                         f2 = 1 - f1;
6088                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6089                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6090                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6091                 }
6092         }
6093         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
6094         R_Mesh_ResetTextureState();
6095         R_SetupShader_Generic_NoTexture(false, false);
6096         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
6097 }
6098
6099 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6100 {
6101         // hacky overloading of the parameters
6102         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
6103         int i;
6104         float color[4];
6105         prvm_edict_t *edict;
6106
6107         GL_CullFace(GL_NONE);
6108         R_SetupShader_Generic_NoTexture(false, false);
6109
6110         for (i = 0;i < numsurfaces;i++)
6111         {
6112                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6113                 switch ((int)PRVM_serveredictfloat(edict, solid))
6114                 {
6115                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6116                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6117                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6118                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6119                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6120                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
6121                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6122                 }
6123                 if (prog == CLVM_prog)
6124                         color[3] *= r_showbboxes_client.value;
6125                 else
6126                         color[3] *= r_showbboxes.value;
6127                 color[3] = bound(0, color[3], 1);
6128                 GL_DepthTest(!r_showdisabledepthtest.integer);
6129                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6130         }
6131 }
6132
6133 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
6134 {
6135         int i;
6136         prvm_edict_t *edict;
6137         vec3_t center;
6138
6139         if (prog == NULL)
6140                 return;
6141
6142         for (i = 0; i < prog->num_edicts; i++)
6143         {
6144                 edict = PRVM_EDICT_NUM(i);
6145                 if (edict->priv.server->free)
6146                         continue;
6147                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6148                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
6149                         continue;
6150                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
6151                         continue;
6152                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6153                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
6154         }
6155 }
6156
6157 static const int nomodelelement3i[24] =
6158 {
6159         5, 2, 0,
6160         5, 1, 2,
6161         5, 0, 3,
6162         5, 3, 1,
6163         0, 2, 4,
6164         2, 1, 4,
6165         3, 0, 4,
6166         1, 3, 4
6167 };
6168
6169 static const unsigned short nomodelelement3s[24] =
6170 {
6171         5, 2, 0,
6172         5, 1, 2,
6173         5, 0, 3,
6174         5, 3, 1,
6175         0, 2, 4,
6176         2, 1, 4,
6177         3, 0, 4,
6178         1, 3, 4
6179 };
6180
6181 static const float nomodelvertex3f[6*3] =
6182 {
6183         -16,   0,   0,
6184          16,   0,   0,
6185           0, -16,   0,
6186           0,  16,   0,
6187           0,   0, -16,
6188           0,   0,  16
6189 };
6190
6191 static const float nomodelcolor4f[6*4] =
6192 {
6193         0.0f, 0.0f, 0.5f, 1.0f,
6194         0.0f, 0.0f, 0.5f, 1.0f,
6195         0.0f, 0.5f, 0.0f, 1.0f,
6196         0.0f, 0.5f, 0.0f, 1.0f,
6197         0.5f, 0.0f, 0.0f, 1.0f,
6198         0.5f, 0.0f, 0.0f, 1.0f
6199 };
6200
6201 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6202 {
6203         int i;
6204         float f1, f2, *c;
6205         float color4f[6*4];
6206
6207         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);
6208
6209         // this is only called once per entity so numsurfaces is always 1, and
6210         // surfacelist is always {0}, so this code does not handle batches
6211
6212         if (rsurface.ent_flags & RENDER_ADDITIVE)
6213         {
6214                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6215                 GL_DepthMask(false);
6216         }
6217         else if (ent->alpha < 1)
6218         {
6219                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6220                 GL_DepthMask(false);
6221         }
6222         else
6223         {
6224                 GL_BlendFunc(GL_ONE, GL_ZERO);
6225                 GL_DepthMask(true);
6226         }
6227         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6228         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6229         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6230         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6231         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6232         for (i = 0, c = color4f;i < 6;i++, c += 4)
6233         {
6234                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
6235                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
6236                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
6237                 c[3] *= ent->alpha;
6238         }
6239         if (r_refdef.fogenabled)
6240         {
6241                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6242                 {
6243                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6244                         f2 = 1 - f1;
6245                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6246                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6247                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6248                 }
6249         }
6250 //      R_Mesh_ResetTextureState();
6251         R_SetupShader_Generic_NoTexture(false, false);
6252         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6253         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6254 }
6255
6256 void R_DrawNoModel(entity_render_t *ent)
6257 {
6258         vec3_t org;
6259         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6260         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6261                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6262         else
6263                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6264 }
6265
6266 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
6267 {
6268         vec3_t right1, right2, diff, normal;
6269
6270         VectorSubtract (org2, org1, normal);
6271
6272         // calculate 'right' vector for start
6273         VectorSubtract (r_refdef.view.origin, org1, diff);
6274         CrossProduct (normal, diff, right1);
6275         VectorNormalize (right1);
6276
6277         // calculate 'right' vector for end
6278         VectorSubtract (r_refdef.view.origin, org2, diff);
6279         CrossProduct (normal, diff, right2);
6280         VectorNormalize (right2);
6281
6282         vert[ 0] = org1[0] + width * right1[0];
6283         vert[ 1] = org1[1] + width * right1[1];
6284         vert[ 2] = org1[2] + width * right1[2];
6285         vert[ 3] = org1[0] - width * right1[0];
6286         vert[ 4] = org1[1] - width * right1[1];
6287         vert[ 5] = org1[2] - width * right1[2];
6288         vert[ 6] = org2[0] - width * right2[0];
6289         vert[ 7] = org2[1] - width * right2[1];
6290         vert[ 8] = org2[2] - width * right2[2];
6291         vert[ 9] = org2[0] + width * right2[0];
6292         vert[10] = org2[1] + width * right2[1];
6293         vert[11] = org2[2] + width * right2[2];
6294 }
6295
6296 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)
6297 {
6298         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6299         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6300         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6301         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6302         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6303         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6304         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6305         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6306         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6307         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6308         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6309         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6310 }
6311
6312 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6313 {
6314         int i;
6315         float *vertex3f;
6316         float v[3];
6317         VectorSet(v, x, y, z);
6318         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6319                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6320                         break;
6321         if (i == mesh->numvertices)
6322         {
6323                 if (mesh->numvertices < mesh->maxvertices)
6324                 {
6325                         VectorCopy(v, vertex3f);
6326                         mesh->numvertices++;
6327                 }
6328                 return mesh->numvertices;
6329         }
6330         else
6331                 return i;
6332 }
6333
6334 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6335 {
6336         int i;
6337         int *e, element[3];
6338         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6339         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6340         e = mesh->element3i + mesh->numtriangles * 3;
6341         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6342         {
6343                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6344                 if (mesh->numtriangles < mesh->maxtriangles)
6345                 {
6346                         *e++ = element[0];
6347                         *e++ = element[1];
6348                         *e++ = element[2];
6349                         mesh->numtriangles++;
6350                 }
6351                 element[1] = element[2];
6352         }
6353 }
6354
6355 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6356 {
6357         int i;
6358         int *e, element[3];
6359         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6360         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6361         e = mesh->element3i + mesh->numtriangles * 3;
6362         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6363         {
6364                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6365                 if (mesh->numtriangles < mesh->maxtriangles)
6366                 {
6367                         *e++ = element[0];
6368                         *e++ = element[1];
6369                         *e++ = element[2];
6370                         mesh->numtriangles++;
6371                 }
6372                 element[1] = element[2];
6373         }
6374 }
6375
6376 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6377 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6378 {
6379         int planenum, planenum2;
6380         int w;
6381         int tempnumpoints;
6382         mplane_t *plane, *plane2;
6383         double maxdist;
6384         double temppoints[2][256*3];
6385         // figure out how large a bounding box we need to properly compute this brush
6386         maxdist = 0;
6387         for (w = 0;w < numplanes;w++)
6388                 maxdist = max(maxdist, fabs(planes[w].dist));
6389         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6390         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6391         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6392         {
6393                 w = 0;
6394                 tempnumpoints = 4;
6395                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6396                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6397                 {
6398                         if (planenum2 == planenum)
6399                                 continue;
6400                         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);
6401                         w = !w;
6402                 }
6403                 if (tempnumpoints < 3)
6404                         continue;
6405                 // generate elements forming a triangle fan for this polygon
6406                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6407         }
6408 }
6409
6410 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)
6411 {
6412         texturelayer_t *layer;
6413         layer = t->currentlayers + t->currentnumlayers++;
6414         layer->type = type;
6415         layer->depthmask = depthmask;
6416         layer->blendfunc1 = blendfunc1;
6417         layer->blendfunc2 = blendfunc2;
6418         layer->texture = texture;
6419         layer->texmatrix = *matrix;
6420         layer->color[0] = r;
6421         layer->color[1] = g;
6422         layer->color[2] = b;
6423         layer->color[3] = a;
6424 }
6425
6426 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
6427 {
6428         if(parms[0] == 0 && parms[1] == 0)
6429                 return false;
6430         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6431                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
6432                         return false;
6433         return true;
6434 }
6435
6436 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6437 {
6438         double index, f;
6439         index = parms[2] + rsurface.shadertime * parms[3];
6440         index -= floor(index);
6441         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
6442         {
6443         default:
6444         case Q3WAVEFUNC_NONE:
6445         case Q3WAVEFUNC_NOISE:
6446         case Q3WAVEFUNC_COUNT:
6447                 f = 0;
6448                 break;
6449         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6450         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6451         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6452         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6453         case Q3WAVEFUNC_TRIANGLE:
6454                 index *= 4;
6455                 f = index - floor(index);
6456                 if (index < 1)
6457                 {
6458                         // f = f;
6459                 }
6460                 else if (index < 2)
6461                         f = 1 - f;
6462                 else if (index < 3)
6463                         f = -f;
6464                 else
6465                         f = -(1 - f);
6466                 break;
6467         }
6468         f = parms[0] + parms[1] * f;
6469         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6470                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
6471         return (float) f;
6472 }
6473
6474 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6475 {
6476         int w, h, idx;
6477         float shadertime;
6478         float f;
6479         float offsetd[2];
6480         float tcmat[12];
6481         matrix4x4_t matrix, temp;
6482         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
6483         // it's better to have one huge fixup every 9 hours than gradual
6484         // degradation over time which looks consistently bad after many hours.
6485         //
6486         // tcmod scroll in particular suffers from this degradation which can't be
6487         // effectively worked around even with floor() tricks because we don't
6488         // know if tcmod scroll is the last tcmod being applied, and for clampmap
6489         // a workaround involving floor() would be incorrect anyway...
6490         shadertime = rsurface.shadertime;
6491         if (shadertime >= 32768.0f)
6492                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
6493         switch(tcmod->tcmod)
6494         {
6495                 case Q3TCMOD_COUNT:
6496                 case Q3TCMOD_NONE:
6497                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6498                                 matrix = r_waterscrollmatrix;
6499                         else
6500                                 matrix = identitymatrix;
6501                         break;
6502                 case Q3TCMOD_ENTITYTRANSLATE:
6503                         // this is used in Q3 to allow the gamecode to control texcoord
6504                         // scrolling on the entity, which is not supported in darkplaces yet.
6505                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6506                         break;
6507                 case Q3TCMOD_ROTATE:
6508                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6509                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
6510                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6511                         break;
6512                 case Q3TCMOD_SCALE:
6513                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6514                         break;
6515                 case Q3TCMOD_SCROLL:
6516                         // this particular tcmod is a "bug for bug" compatible one with regards to
6517                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
6518                         // specifically did the wrapping and so we must mimic that...
6519                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
6520                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
6521                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
6522                         break;
6523                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6524                         w = (int) tcmod->parms[0];
6525                         h = (int) tcmod->parms[1];
6526                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
6527                         f = f - floor(f);
6528                         idx = (int) floor(f * w * h);
6529                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6530                         break;
6531                 case Q3TCMOD_STRETCH:
6532                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6533                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6534                         break;
6535                 case Q3TCMOD_TRANSFORM:
6536                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6537                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6538                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6539                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6540                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6541                         break;
6542                 case Q3TCMOD_TURBULENT:
6543                         // this is handled in the RSurf_PrepareVertices function
6544                         matrix = identitymatrix;
6545                         break;
6546         }
6547         temp = *texmatrix;
6548         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6549 }
6550
6551 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6552 {
6553         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
6554         char name[MAX_QPATH];
6555         skinframe_t *skinframe;
6556         unsigned char pixels[296*194];
6557         strlcpy(cache->name, skinname, sizeof(cache->name));
6558         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6559         if (developer_loading.integer)
6560                 Con_Printf("loading %s\n", name);
6561         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6562         if (!skinframe || !skinframe->base)
6563         {
6564                 unsigned char *f;
6565                 fs_offset_t filesize;
6566                 skinframe = NULL;
6567                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6568                 if (f)
6569                 {
6570                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
6571                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6572                         Mem_Free(f);
6573                 }
6574         }
6575         cache->skinframe = skinframe;
6576 }
6577
6578 texture_t *R_GetCurrentTexture(texture_t *t)
6579 {
6580         int i, q;
6581         const entity_render_t *ent = rsurface.entity;
6582         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
6583         q3shaderinfo_layer_tcmod_t *tcmod;
6584         float specularscale = 0.0f;
6585
6586         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
6587                 return t->currentframe;
6588         t->update_lastrenderframe = r_textureframe;
6589         t->update_lastrenderentity = (void *)ent;
6590
6591         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
6592                 t->camera_entity = ent->entitynumber;
6593         else
6594                 t->camera_entity = 0;
6595
6596         // switch to an alternate material if this is a q1bsp animated material
6597         {
6598                 texture_t *texture = t;
6599                 int s = rsurface.ent_skinnum;
6600                 if ((unsigned int)s >= (unsigned int)model->numskins)
6601                         s = 0;
6602                 if (model->skinscenes)
6603                 {
6604                         if (model->skinscenes[s].framecount > 1)
6605                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6606                         else
6607                                 s = model->skinscenes[s].firstframe;
6608                 }
6609                 if (s > 0)
6610                         t = t + s * model->num_surfaces;
6611                 if (t->animated)
6612                 {
6613                         // use an alternate animation if the entity's frame is not 0,
6614                         // and only if the texture has an alternate animation
6615                         if (t->animated == 2) // q2bsp
6616                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
6617                         else if (rsurface.ent_alttextures && t->anim_total[1])
6618                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
6619                         else
6620                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
6621                 }
6622                 texture->currentframe = t;
6623         }
6624
6625         // update currentskinframe to be a qw skin or animation frame
6626         if (rsurface.ent_qwskin >= 0)
6627         {
6628                 i = rsurface.ent_qwskin;
6629                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6630                 {
6631                         r_qwskincache_size = cl.maxclients;
6632                         if (r_qwskincache)
6633                                 Mem_Free(r_qwskincache);
6634                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6635                 }
6636                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6637                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6638                 t->currentskinframe = r_qwskincache[i].skinframe;
6639                 if (t->materialshaderpass && t->currentskinframe == NULL)
6640                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6641         }
6642         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
6643                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6644         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
6645                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
6646
6647         t->currentmaterialflags = t->basematerialflags;
6648         t->currentalpha = rsurface.entity->alpha * t->basealpha;
6649         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_water.integer || r_novis.integer || r_trippy.integer))
6650                 t->currentalpha *= r_wateralpha.value;
6651         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
6652                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
6653         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
6654                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
6655
6656         // decide on which type of lighting to use for this surface
6657         if (rsurface.entity->render_modellight_forced)
6658                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6659         if (rsurface.entity->render_rtlight_disabled)
6660                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
6661         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
6662         {
6663                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
6664                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
6665                 for (q = 0; q < 3; q++)
6666                 {
6667                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
6668                         t->render_modellight_lightdir[q] = q == 2;
6669                         t->render_modellight_ambient[q] = 1;
6670                         t->render_modellight_diffuse[q] = 0;
6671                         t->render_modellight_specular[q] = 0;
6672                         t->render_lightmap_ambient[q] = 0;
6673                         t->render_lightmap_diffuse[q] = 0;
6674                         t->render_lightmap_specular[q] = 0;
6675                         t->render_rtlight_diffuse[q] = 0;
6676                         t->render_rtlight_specular[q] = 0;
6677                 }
6678         }
6679         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
6680         {
6681                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
6682                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
6683                 for (q = 0; q < 3; q++)
6684                 {
6685                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6686                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6687                         t->render_modellight_lightdir[q] = q == 2;
6688                         t->render_modellight_diffuse[q] = 0;
6689                         t->render_modellight_specular[q] = 0;
6690                         t->render_lightmap_ambient[q] = 0;
6691                         t->render_lightmap_diffuse[q] = 0;
6692                         t->render_lightmap_specular[q] = 0;
6693                         t->render_rtlight_diffuse[q] = 0;
6694                         t->render_rtlight_specular[q] = 0;
6695                 }
6696         }
6697         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
6698         {
6699                 // ambient + single direction light (modellight)
6700                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6701                 for (q = 0; q < 3; q++)
6702                 {
6703                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6704                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6705                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6706                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6707                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6708                         t->render_lightmap_ambient[q] = 0;
6709                         t->render_lightmap_diffuse[q] = 0;
6710                         t->render_lightmap_specular[q] = 0;
6711                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6712                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6713                 }
6714         }
6715         else
6716         {
6717                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
6718                 for (q = 0; q < 3; q++)
6719                 {
6720                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6721                         t->render_modellight_lightdir[q] = q == 2;
6722                         t->render_modellight_ambient[q] = 0;
6723                         t->render_modellight_diffuse[q] = 0;
6724                         t->render_modellight_specular[q] = 0;
6725                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
6726                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
6727                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
6728                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6729                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6730                 }
6731         }
6732
6733         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
6734         {
6735                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
6736                 // attribute, we punt it to the lightmap path and hope for the best,
6737                 // but lighting doesn't work.
6738                 //
6739                 // FIXME: this is fine for effects but CSQC polygons should be subject
6740                 // to lighting.
6741                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
6742                 for (q = 0; q < 3; q++)
6743                 {
6744                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6745                         t->render_modellight_lightdir[q] = q == 2;
6746                         t->render_modellight_ambient[q] = 0;
6747                         t->render_modellight_diffuse[q] = 0;
6748                         t->render_modellight_specular[q] = 0;
6749                         t->render_lightmap_ambient[q] = 0;
6750                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6751                         t->render_lightmap_specular[q] = 0;
6752                         t->render_rtlight_diffuse[q] = 0;
6753                         t->render_rtlight_specular[q] = 0;
6754                 }
6755         }
6756
6757         for (q = 0; q < 3; q++)
6758         {
6759                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
6760                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
6761         }
6762
6763         if (rsurface.ent_flags & RENDER_ADDITIVE)
6764                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6765         else if (t->currentalpha < 1)
6766                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6767         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
6768         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6769                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
6770         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6771                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6772         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6773                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6774         if (t->backgroundshaderpass)
6775                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6776         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6777         {
6778                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
6779                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6780         }
6781         else
6782                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
6783         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
6784         {
6785                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
6786                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
6787         }
6788         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6789                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6790
6791         // there is no tcmod
6792         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6793         {
6794                 t->currenttexmatrix = r_waterscrollmatrix;
6795                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6796         }
6797         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6798         {
6799                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6800                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6801         }
6802
6803         if (t->materialshaderpass)
6804                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6805                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6806
6807         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
6808         if (t->currentskinframe->qpixels)
6809                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6810         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6811         if (!t->basetexture)
6812                 t->basetexture = r_texture_notexture;
6813         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6814         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6815         t->nmaptexture = t->currentskinframe->nmap;
6816         if (!t->nmaptexture)
6817                 t->nmaptexture = r_texture_blanknormalmap;
6818         t->glosstexture = r_texture_black;
6819         t->glowtexture = t->currentskinframe->glow;
6820         t->fogtexture = t->currentskinframe->fog;
6821         t->reflectmasktexture = t->currentskinframe->reflect;
6822         if (t->backgroundshaderpass)
6823         {
6824                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
6825                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6826                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6827                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6828                 t->backgroundglosstexture = r_texture_black;
6829                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6830                 if (!t->backgroundnmaptexture)
6831                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6832                 // make sure that if glow is going to be used, both textures are not NULL
6833                 if (!t->backgroundglowtexture && t->glowtexture)
6834                         t->backgroundglowtexture = r_texture_black;
6835                 if (!t->glowtexture && t->backgroundglowtexture)
6836                         t->glowtexture = r_texture_black;
6837         }
6838         else
6839         {
6840                 t->backgroundbasetexture = r_texture_white;
6841                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6842                 t->backgroundglosstexture = r_texture_black;
6843                 t->backgroundglowtexture = NULL;
6844         }
6845         t->specularpower = r_shadow_glossexponent.value;
6846         // TODO: store reference values for these in the texture?
6847         if (r_shadow_gloss.integer > 0)
6848         {
6849                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6850                 {
6851                         if (r_shadow_glossintensity.value > 0)
6852                         {
6853                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6854                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6855                                 specularscale = r_shadow_glossintensity.value;
6856                         }
6857                 }
6858                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6859                 {
6860                         t->glosstexture = r_texture_white;
6861                         t->backgroundglosstexture = r_texture_white;
6862                         specularscale = r_shadow_gloss2intensity.value;
6863                         t->specularpower = r_shadow_gloss2exponent.value;
6864                 }
6865         }
6866         specularscale *= t->specularscalemod;
6867         t->specularpower *= t->specularpowermod;
6868
6869         // lightmaps mode looks bad with dlights using actual texturing, so turn
6870         // off the colormap and glossmap, but leave the normalmap on as it still
6871         // accurately represents the shading involved
6872         if (gl_lightmaps.integer)
6873         {
6874                 t->basetexture = r_texture_grey128;
6875                 t->pantstexture = r_texture_black;
6876                 t->shirttexture = r_texture_black;
6877                 if (gl_lightmaps.integer < 2)
6878                         t->nmaptexture = r_texture_blanknormalmap;
6879                 t->glosstexture = r_texture_black;
6880                 t->glowtexture = NULL;
6881                 t->fogtexture = NULL;
6882                 t->reflectmasktexture = NULL;
6883                 t->backgroundbasetexture = NULL;
6884                 if (gl_lightmaps.integer < 2)
6885                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6886                 t->backgroundglosstexture = r_texture_black;
6887                 t->backgroundglowtexture = NULL;
6888                 specularscale = 0;
6889                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6890         }
6891
6892         if (specularscale != 1.0f)
6893         {
6894                 for (q = 0; q < 3; q++)
6895                 {
6896                         t->render_modellight_specular[q] *= specularscale;
6897                         t->render_lightmap_specular[q] *= specularscale;
6898                         t->render_rtlight_specular[q] *= specularscale;
6899                 }
6900         }
6901
6902         t->currentnumlayers = 0;
6903         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6904         {
6905                 int blendfunc1, blendfunc2;
6906                 qboolean depthmask;
6907                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6908                 {
6909                         blendfunc1 = GL_SRC_ALPHA;
6910                         blendfunc2 = GL_ONE;
6911                 }
6912                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6913                 {
6914                         blendfunc1 = GL_SRC_ALPHA;
6915                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6916                 }
6917                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6918                 {
6919                         blendfunc1 = t->customblendfunc[0];
6920                         blendfunc2 = t->customblendfunc[1];
6921                 }
6922                 else
6923                 {
6924                         blendfunc1 = GL_ONE;
6925                         blendfunc2 = GL_ZERO;
6926                 }
6927                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6928                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6929                 {
6930                         // basic lit geometry
6931                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
6932                         // add pants/shirt if needed
6933                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
6934                                 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);
6935                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
6936                                 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);
6937                 }
6938                 else
6939                 {
6940                         // basic lit geometry
6941                         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);
6942                         // add pants/shirt if needed
6943                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
6944                                 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);
6945                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
6946                                 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);
6947                         // now add ambient passes if needed
6948                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
6949                         {
6950                                 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);
6951                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
6952                                         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);
6953                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
6954                                         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);
6955                         }
6956                 }
6957                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
6958                         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);
6959                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6960                 {
6961                         // if this is opaque use alpha blend which will darken the earlier
6962                         // passes cheaply.
6963                         //
6964                         // if this is an alpha blended material, all the earlier passes
6965                         // were darkened by fog already, so we only need to add the fog
6966                         // color ontop through the fog mask texture
6967                         //
6968                         // if this is an additive blended material, all the earlier passes
6969                         // were darkened by fog already, and we should not add fog color
6970                         // (because the background was not darkened, there is no fog color
6971                         // that was lost behind it).
6972                         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);
6973                 }
6974         }
6975
6976         return t;
6977 }
6978
6979 rsurfacestate_t rsurface;
6980
6981 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6982 {
6983         dp_model_t *model = ent->model;
6984         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6985         //      return;
6986         rsurface.entity = (entity_render_t *)ent;
6987         rsurface.skeleton = ent->skeleton;
6988         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
6989         rsurface.ent_skinnum = ent->skinnum;
6990         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;
6991         rsurface.ent_flags = ent->flags;
6992         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
6993                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
6994         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
6995         rsurface.matrix = ent->matrix;
6996         rsurface.inversematrix = ent->inversematrix;
6997         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6998         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6999         R_EntityMatrix(&rsurface.matrix);
7000         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7001         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7002         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
7003         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7004         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7005         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7006         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7007         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7008         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7009         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7010         if (ent->model->brush.submodel && !prepass)
7011         {
7012                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7013                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7014         }
7015         // if the animcache code decided it should use the shader path, skip the deform step
7016         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
7017         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
7018         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
7019         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
7020         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
7021         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
7022         {
7023                 if (ent->animcache_vertex3f)
7024                 {
7025                         r_refdef.stats[r_stat_batch_entitycache_count]++;
7026                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
7027                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
7028                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
7029                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7030                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
7031                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
7032                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7033                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
7034                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
7035                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7036                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
7037                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
7038                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7039                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
7040                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
7041                 }
7042                 else if (wanttangents)
7043                 {
7044                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7045                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7046                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7047                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7048                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7049                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7050                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7051                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7052                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7053                         rsurface.modelvertex3f_vertexbuffer = NULL;
7054                         rsurface.modelvertex3f_bufferoffset = 0;
7055                         rsurface.modelvertex3f_vertexbuffer = 0;
7056                         rsurface.modelvertex3f_bufferoffset = 0;
7057                         rsurface.modelsvector3f_vertexbuffer = 0;
7058                         rsurface.modelsvector3f_bufferoffset = 0;
7059                         rsurface.modeltvector3f_vertexbuffer = 0;
7060                         rsurface.modeltvector3f_bufferoffset = 0;
7061                         rsurface.modelnormal3f_vertexbuffer = 0;
7062                         rsurface.modelnormal3f_bufferoffset = 0;
7063                 }
7064                 else if (wantnormals)
7065                 {
7066                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7067                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7068                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7069                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7070                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7071                         rsurface.modelsvector3f = NULL;
7072                         rsurface.modeltvector3f = NULL;
7073                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7074                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7075                         rsurface.modelvertex3f_vertexbuffer = NULL;
7076                         rsurface.modelvertex3f_bufferoffset = 0;
7077                         rsurface.modelvertex3f_vertexbuffer = 0;
7078                         rsurface.modelvertex3f_bufferoffset = 0;
7079                         rsurface.modelsvector3f_vertexbuffer = 0;
7080                         rsurface.modelsvector3f_bufferoffset = 0;
7081                         rsurface.modeltvector3f_vertexbuffer = 0;
7082                         rsurface.modeltvector3f_bufferoffset = 0;
7083                         rsurface.modelnormal3f_vertexbuffer = 0;
7084                         rsurface.modelnormal3f_bufferoffset = 0;
7085                 }
7086                 else
7087                 {
7088                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7089                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7090                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7091                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7092                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7093                         rsurface.modelsvector3f = NULL;
7094                         rsurface.modeltvector3f = NULL;
7095                         rsurface.modelnormal3f = NULL;
7096                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7097                         rsurface.modelvertex3f_vertexbuffer = NULL;
7098                         rsurface.modelvertex3f_bufferoffset = 0;
7099                         rsurface.modelvertex3f_vertexbuffer = 0;
7100                         rsurface.modelvertex3f_bufferoffset = 0;
7101                         rsurface.modelsvector3f_vertexbuffer = 0;
7102                         rsurface.modelsvector3f_bufferoffset = 0;
7103                         rsurface.modeltvector3f_vertexbuffer = 0;
7104                         rsurface.modeltvector3f_bufferoffset = 0;
7105                         rsurface.modelnormal3f_vertexbuffer = 0;
7106                         rsurface.modelnormal3f_bufferoffset = 0;
7107                 }
7108                 rsurface.modelgeneratedvertex = true;
7109         }
7110         else
7111         {
7112                 if (rsurface.entityskeletaltransform3x4)
7113                 {
7114                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
7115                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
7116                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
7117                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
7118                 }
7119                 else
7120                 {
7121                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
7122                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
7123                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
7124                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
7125                 }
7126                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7127                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.data_vertex3f_vertexbuffer;
7128                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.data_vertex3f_bufferoffset;
7129                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7130                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.data_svector3f_vertexbuffer;
7131                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.data_svector3f_bufferoffset;
7132                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7133                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.data_tvector3f_vertexbuffer;
7134                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.data_tvector3f_bufferoffset;
7135                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7136                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.data_normal3f_vertexbuffer;
7137                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.data_normal3f_bufferoffset;
7138                 rsurface.modelgeneratedvertex = false;
7139         }
7140         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7141         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.data_lightmapcolor4f_vertexbuffer;
7142         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.data_lightmapcolor4f_bufferoffset;
7143         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7144         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.data_texcoordtexture2f_vertexbuffer;
7145         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.data_texcoordtexture2f_bufferoffset;
7146         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7147         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.data_texcoordlightmap2f_vertexbuffer;
7148         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.data_texcoordlightmap2f_bufferoffset;
7149         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
7150         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.data_skeletalindex4ub_vertexbuffer;
7151         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.data_skeletalindex4ub_bufferoffset;
7152         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
7153         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.data_skeletalweight4ub_vertexbuffer;
7154         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.data_skeletalweight4ub_bufferoffset;
7155         rsurface.modelelement3i = model->surfmesh.data_element3i;
7156         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7157         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7158         rsurface.modelelement3s = model->surfmesh.data_element3s;
7159         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7160         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7161         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7162         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7163         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7164         rsurface.modelsurfaces = model->data_surfaces;
7165         rsurface.batchgeneratedvertex = false;
7166         rsurface.batchfirstvertex = 0;
7167         rsurface.batchnumvertices = 0;
7168         rsurface.batchfirsttriangle = 0;
7169         rsurface.batchnumtriangles = 0;
7170         rsurface.batchvertex3f  = NULL;
7171         rsurface.batchvertex3f_vertexbuffer = NULL;
7172         rsurface.batchvertex3f_bufferoffset = 0;
7173         rsurface.batchsvector3f = NULL;
7174         rsurface.batchsvector3f_vertexbuffer = NULL;
7175         rsurface.batchsvector3f_bufferoffset = 0;
7176         rsurface.batchtvector3f = NULL;
7177         rsurface.batchtvector3f_vertexbuffer = NULL;
7178         rsurface.batchtvector3f_bufferoffset = 0;
7179         rsurface.batchnormal3f  = NULL;
7180         rsurface.batchnormal3f_vertexbuffer = NULL;
7181         rsurface.batchnormal3f_bufferoffset = 0;
7182         rsurface.batchlightmapcolor4f = NULL;
7183         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7184         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7185         rsurface.batchtexcoordtexture2f = NULL;
7186         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7187         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7188         rsurface.batchtexcoordlightmap2f = NULL;
7189         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7190         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7191         rsurface.batchskeletalindex4ub = NULL;
7192         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7193         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7194         rsurface.batchskeletalweight4ub = NULL;
7195         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7196         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7197         rsurface.batchelement3i = NULL;
7198         rsurface.batchelement3i_indexbuffer = NULL;
7199         rsurface.batchelement3i_bufferoffset = 0;
7200         rsurface.batchelement3s = NULL;
7201         rsurface.batchelement3s_indexbuffer = NULL;
7202         rsurface.batchelement3s_bufferoffset = 0;
7203         rsurface.forcecurrenttextureupdate = false;
7204 }
7205
7206 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)
7207 {
7208         rsurface.entity = r_refdef.scene.worldentity;
7209         rsurface.skeleton = NULL;
7210         rsurface.ent_skinnum = 0;
7211         rsurface.ent_qwskin = -1;
7212         rsurface.ent_flags = entflags;
7213         rsurface.shadertime = r_refdef.scene.time - shadertime;
7214         rsurface.modelnumvertices = numvertices;
7215         rsurface.modelnumtriangles = numtriangles;
7216         rsurface.matrix = *matrix;
7217         rsurface.inversematrix = *inversematrix;
7218         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7219         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7220         R_EntityMatrix(&rsurface.matrix);
7221         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7222         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7223         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7224         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7225         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7226         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7227         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7228         rsurface.frameblend[0].lerp = 1;
7229         rsurface.ent_alttextures = false;
7230         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7231         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7232         rsurface.entityskeletaltransform3x4 = NULL;
7233         rsurface.entityskeletaltransform3x4buffer = NULL;
7234         rsurface.entityskeletaltransform3x4offset = 0;
7235         rsurface.entityskeletaltransform3x4size = 0;
7236         rsurface.entityskeletalnumtransforms = 0;
7237         r_refdef.stats[r_stat_batch_entitycustom_count]++;
7238         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
7239         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
7240         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
7241         if (wanttangents)
7242         {
7243                 rsurface.modelvertex3f = (float *)vertex3f;
7244                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7245                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7246                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7247         }
7248         else if (wantnormals)
7249         {
7250                 rsurface.modelvertex3f = (float *)vertex3f;
7251                 rsurface.modelsvector3f = NULL;
7252                 rsurface.modeltvector3f = NULL;
7253                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7254         }
7255         else
7256         {
7257                 rsurface.modelvertex3f = (float *)vertex3f;
7258                 rsurface.modelsvector3f = NULL;
7259                 rsurface.modeltvector3f = NULL;
7260                 rsurface.modelnormal3f = NULL;
7261         }
7262         rsurface.modelvertex3f_vertexbuffer = 0;
7263         rsurface.modelvertex3f_bufferoffset = 0;
7264         rsurface.modelsvector3f_vertexbuffer = 0;
7265         rsurface.modelsvector3f_bufferoffset = 0;
7266         rsurface.modeltvector3f_vertexbuffer = 0;
7267         rsurface.modeltvector3f_bufferoffset = 0;
7268         rsurface.modelnormal3f_vertexbuffer = 0;
7269         rsurface.modelnormal3f_bufferoffset = 0;
7270         rsurface.modelgeneratedvertex = true;
7271         rsurface.modellightmapcolor4f  = (float *)color4f;
7272         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7273         rsurface.modellightmapcolor4f_bufferoffset = 0;
7274         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7275         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7276         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7277         rsurface.modeltexcoordlightmap2f  = NULL;
7278         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7279         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7280         rsurface.modelskeletalindex4ub = NULL;
7281         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
7282         rsurface.modelskeletalindex4ub_bufferoffset = 0;
7283         rsurface.modelskeletalweight4ub = NULL;
7284         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
7285         rsurface.modelskeletalweight4ub_bufferoffset = 0;
7286         rsurface.modelelement3i = (int *)element3i;
7287         rsurface.modelelement3i_indexbuffer = NULL;
7288         rsurface.modelelement3i_bufferoffset = 0;
7289         rsurface.modelelement3s = (unsigned short *)element3s;
7290         rsurface.modelelement3s_indexbuffer = NULL;
7291         rsurface.modelelement3s_bufferoffset = 0;
7292         rsurface.modellightmapoffsets = NULL;
7293         rsurface.modelsurfaces = NULL;
7294         rsurface.batchgeneratedvertex = false;
7295         rsurface.batchfirstvertex = 0;
7296         rsurface.batchnumvertices = 0;
7297         rsurface.batchfirsttriangle = 0;
7298         rsurface.batchnumtriangles = 0;
7299         rsurface.batchvertex3f  = NULL;
7300         rsurface.batchvertex3f_vertexbuffer = NULL;
7301         rsurface.batchvertex3f_bufferoffset = 0;
7302         rsurface.batchsvector3f = NULL;
7303         rsurface.batchsvector3f_vertexbuffer = NULL;
7304         rsurface.batchsvector3f_bufferoffset = 0;
7305         rsurface.batchtvector3f = NULL;
7306         rsurface.batchtvector3f_vertexbuffer = NULL;
7307         rsurface.batchtvector3f_bufferoffset = 0;
7308         rsurface.batchnormal3f  = NULL;
7309         rsurface.batchnormal3f_vertexbuffer = NULL;
7310         rsurface.batchnormal3f_bufferoffset = 0;
7311         rsurface.batchlightmapcolor4f = NULL;
7312         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7313         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7314         rsurface.batchtexcoordtexture2f = NULL;
7315         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7316         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7317         rsurface.batchtexcoordlightmap2f = NULL;
7318         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7319         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7320         rsurface.batchskeletalindex4ub = NULL;
7321         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7322         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7323         rsurface.batchskeletalweight4ub = NULL;
7324         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7325         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7326         rsurface.batchelement3i = NULL;
7327         rsurface.batchelement3i_indexbuffer = NULL;
7328         rsurface.batchelement3i_bufferoffset = 0;
7329         rsurface.batchelement3s = NULL;
7330         rsurface.batchelement3s_indexbuffer = NULL;
7331         rsurface.batchelement3s_bufferoffset = 0;
7332         rsurface.forcecurrenttextureupdate = true;
7333
7334         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7335         {
7336                 if ((wantnormals || wanttangents) && !normal3f)
7337                 {
7338                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7339                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7340                 }
7341                 if (wanttangents && !svector3f)
7342                 {
7343                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7344                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7345                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7346                 }
7347         }
7348 }
7349
7350 float RSurf_FogPoint(const float *v)
7351 {
7352         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7353         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7354         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7355         float FogHeightFade = r_refdef.fogheightfade;
7356         float fogfrac;
7357         unsigned int fogmasktableindex;
7358         if (r_refdef.fogplaneviewabove)
7359                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7360         else
7361                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7362         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7363         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7364 }
7365
7366 float RSurf_FogVertex(const float *v)
7367 {
7368         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7369         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7370         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7371         float FogHeightFade = rsurface.fogheightfade;
7372         float fogfrac;
7373         unsigned int fogmasktableindex;
7374         if (r_refdef.fogplaneviewabove)
7375                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7376         else
7377                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7378         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7379         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7380 }
7381
7382 void RSurf_UploadBuffersForBatch(void)
7383 {
7384         // upload buffer data for generated vertex data (dynamicvertex case) or index data (copytriangles case) and models that lack it to begin with (e.g. DrawQ_FlushUI)
7385         // note that if rsurface.batchvertex3f_vertexbuffer is NULL, dynamicvertex is forced as we don't account for the proper base vertex here.
7386         if (rsurface.batchvertex3f && !rsurface.batchvertex3f_vertexbuffer)
7387                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
7388         if (rsurface.batchsvector3f && !rsurface.batchsvector3f_vertexbuffer)
7389                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
7390         if (rsurface.batchtvector3f && !rsurface.batchtvector3f_vertexbuffer)
7391                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
7392         if (rsurface.batchnormal3f && !rsurface.batchnormal3f_vertexbuffer)
7393                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
7394         if (rsurface.batchlightmapcolor4f && !rsurface.batchlightmapcolor4f_vertexbuffer)
7395                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
7396         if (rsurface.batchtexcoordtexture2f && !rsurface.batchtexcoordtexture2f_vertexbuffer)
7397                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
7398         if (rsurface.batchtexcoordlightmap2f && !rsurface.batchtexcoordlightmap2f_vertexbuffer)
7399                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
7400         if (rsurface.batchskeletalindex4ub && !rsurface.batchskeletalindex4ub_vertexbuffer)
7401                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
7402         if (rsurface.batchskeletalweight4ub && !rsurface.batchskeletalweight4ub_vertexbuffer)
7403                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
7404
7405         if (rsurface.batchelement3s && !rsurface.batchelement3s_indexbuffer)
7406                 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
7407         else if (rsurface.batchelement3i && !rsurface.batchelement3i_indexbuffer)
7408                 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
7409
7410         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7411         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7412         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7413         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7414         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7415         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7416         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7417         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
7418         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
7419         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
7420 }
7421
7422 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7423 {
7424         int i;
7425         for (i = 0;i < numelements;i++)
7426                 outelement3i[i] = inelement3i[i] + adjust;
7427 }
7428
7429 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7430 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7431 {
7432         int deformindex;
7433         int firsttriangle;
7434         int numtriangles;
7435         int firstvertex;
7436         int endvertex;
7437         int numvertices;
7438         int surfacefirsttriangle;
7439         int surfacenumtriangles;
7440         int surfacefirstvertex;
7441         int surfaceendvertex;
7442         int surfacenumvertices;
7443         int batchnumsurfaces = texturenumsurfaces;
7444         int batchnumvertices;
7445         int batchnumtriangles;
7446         int i, j;
7447         qboolean gaps;
7448         qboolean dynamicvertex;
7449         float amplitude;
7450         float animpos;
7451         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7452         float waveparms[4];
7453         unsigned char *ub;
7454         q3shaderinfo_deform_t *deform;
7455         const msurface_t *surface, *firstsurface;
7456         if (!texturenumsurfaces)
7457                 return;
7458         // find vertex range of this surface batch
7459         gaps = false;
7460         firstsurface = texturesurfacelist[0];
7461         firsttriangle = firstsurface->num_firsttriangle;
7462         batchnumvertices = 0;
7463         batchnumtriangles = 0;
7464         firstvertex = endvertex = firstsurface->num_firstvertex;
7465         for (i = 0;i < texturenumsurfaces;i++)
7466         {
7467                 surface = texturesurfacelist[i];
7468                 if (surface != firstsurface + i)
7469                         gaps = true;
7470                 surfacefirstvertex = surface->num_firstvertex;
7471                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
7472                 surfacenumvertices = surface->num_vertices;
7473                 surfacenumtriangles = surface->num_triangles;
7474                 if (firstvertex > surfacefirstvertex)
7475                         firstvertex = surfacefirstvertex;
7476                 if (endvertex < surfaceendvertex)
7477                         endvertex = surfaceendvertex;
7478                 batchnumvertices += surfacenumvertices;
7479                 batchnumtriangles += surfacenumtriangles;
7480         }
7481
7482         r_refdef.stats[r_stat_batch_batches]++;
7483         if (gaps)
7484                 r_refdef.stats[r_stat_batch_withgaps]++;
7485         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
7486         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
7487         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
7488
7489         // we now know the vertex range used, and if there are any gaps in it
7490         rsurface.batchfirstvertex = firstvertex;
7491         rsurface.batchnumvertices = endvertex - firstvertex;
7492         rsurface.batchfirsttriangle = firsttriangle;
7493         rsurface.batchnumtriangles = batchnumtriangles;
7494
7495         // check if any dynamic vertex processing must occur
7496         dynamicvertex = false;
7497
7498         // we must use vertexbuffers for rendering, we can upload vertex buffers
7499         // easily enough but if the basevertex is non-zero it becomes more
7500         // difficult, so force dynamicvertex path in that case - it's suboptimal
7501         // but the most optimal case is to have the geometry sources provide their
7502         // own anyway.
7503         if (!rsurface.modelvertex3f_vertexbuffer && firstvertex != 0)
7504                 dynamicvertex = true;
7505
7506         // a cvar to force the dynamic vertex path to be taken, for debugging
7507         if (r_batch_debugdynamicvertexpath.integer)
7508         {
7509                 if (!dynamicvertex)
7510                 {
7511                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
7512                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
7513                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
7514                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
7515                 }
7516                 dynamicvertex = true;
7517         }
7518
7519         // if there is a chance of animated vertex colors, it's a dynamic batch
7520         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
7521         {
7522                 if (!dynamicvertex)
7523                 {
7524                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
7525                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
7526                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
7527                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
7528                 }
7529                 dynamicvertex = true;
7530         }
7531
7532         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
7533         {
7534                 switch (deform->deform)
7535                 {
7536                 default:
7537                 case Q3DEFORM_PROJECTIONSHADOW:
7538                 case Q3DEFORM_TEXT0:
7539                 case Q3DEFORM_TEXT1:
7540                 case Q3DEFORM_TEXT2:
7541                 case Q3DEFORM_TEXT3:
7542                 case Q3DEFORM_TEXT4:
7543                 case Q3DEFORM_TEXT5:
7544                 case Q3DEFORM_TEXT6:
7545                 case Q3DEFORM_TEXT7:
7546                 case Q3DEFORM_NONE:
7547                         break;
7548                 case Q3DEFORM_AUTOSPRITE:
7549                         if (!dynamicvertex)
7550                         {
7551                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
7552                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
7553                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
7554                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
7555                         }
7556                         dynamicvertex = true;
7557                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
7558                         break;
7559                 case Q3DEFORM_AUTOSPRITE2:
7560                         if (!dynamicvertex)
7561                         {
7562                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
7563                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
7564                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
7565                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
7566                         }
7567                         dynamicvertex = true;
7568                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7569                         break;
7570                 case Q3DEFORM_NORMAL:
7571                         if (!dynamicvertex)
7572                         {
7573                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
7574                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
7575                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
7576                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
7577                         }
7578                         dynamicvertex = true;
7579                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7580                         break;
7581                 case Q3DEFORM_WAVE:
7582                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7583                                 break; // if wavefunc is a nop, ignore this transform
7584                         if (!dynamicvertex)
7585                         {
7586                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
7587                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
7588                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
7589                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
7590                         }
7591                         dynamicvertex = true;
7592                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7593                         break;
7594                 case Q3DEFORM_BULGE:
7595                         if (!dynamicvertex)
7596                         {
7597                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
7598                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
7599                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
7600                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
7601                         }
7602                         dynamicvertex = true;
7603                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7604                         break;
7605                 case Q3DEFORM_MOVE:
7606                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7607                                 break; // if wavefunc is a nop, ignore this transform
7608                         if (!dynamicvertex)
7609                         {
7610                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
7611                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
7612                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
7613                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
7614                         }
7615                         dynamicvertex = true;
7616                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7617                         break;
7618                 }
7619         }
7620         if (rsurface.texture->materialshaderpass)
7621         {
7622                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
7623                 {
7624                 default:
7625                 case Q3TCGEN_TEXTURE:
7626                         break;
7627                 case Q3TCGEN_LIGHTMAP:
7628                         if (!dynamicvertex)
7629                         {
7630                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
7631                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
7632                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
7633                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
7634                         }
7635                         dynamicvertex = true;
7636                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
7637                         break;
7638                 case Q3TCGEN_VECTOR:
7639                         if (!dynamicvertex)
7640                         {
7641                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
7642                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
7643                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
7644                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
7645                         }
7646                         dynamicvertex = true;
7647                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7648                         break;
7649                 case Q3TCGEN_ENVIRONMENT:
7650                         if (!dynamicvertex)
7651                         {
7652                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
7653                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
7654                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
7655                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
7656                         }
7657                         dynamicvertex = true;
7658                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
7659                         break;
7660                 }
7661                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7662                 {
7663                         if (!dynamicvertex)
7664                         {
7665                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
7666                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
7667                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
7668                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
7669                         }
7670                         dynamicvertex = true;
7671                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7672                 }
7673         }
7674
7675         // the caller can specify BATCHNEED_NOGAPS to force a batch with
7676         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
7677         // we ensure this by treating the vertex batch as dynamic...
7678         if ((batchneed & BATCHNEED_ALWAYSCOPY) || ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0)))
7679         {
7680                 if (!dynamicvertex)
7681                 {
7682                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
7683                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
7684                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
7685                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
7686                 }
7687                 dynamicvertex = true;
7688         }
7689
7690         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
7691         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
7692                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
7693
7694         rsurface.batchvertex3f = rsurface.modelvertex3f;
7695         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
7696         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7697         rsurface.batchsvector3f = rsurface.modelsvector3f;
7698         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
7699         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7700         rsurface.batchtvector3f = rsurface.modeltvector3f;
7701         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
7702         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7703         rsurface.batchnormal3f = rsurface.modelnormal3f;
7704         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
7705         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7706         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
7707         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
7708         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
7709         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
7710         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
7711         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7712         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7713         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
7714         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7715         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
7716         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
7717         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
7718         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
7719         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
7720         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
7721         rsurface.batchelement3i = rsurface.modelelement3i;
7722         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
7723         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
7724         rsurface.batchelement3s = rsurface.modelelement3s;
7725         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
7726         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
7727         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
7728         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
7729         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
7730         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
7731         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
7732
7733         // if any dynamic vertex processing has to occur in software, we copy the
7734         // entire surface list together before processing to rebase the vertices
7735         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
7736         //
7737         // if any gaps exist and we do not have a static vertex buffer, we have to
7738         // copy the surface list together to avoid wasting upload bandwidth on the
7739         // vertices in the gaps.
7740         //
7741         // if gaps exist and we have a static vertex buffer, we can choose whether
7742         // to combine the index buffer ranges into one dynamic index buffer or
7743         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
7744         //
7745         // in many cases the batch is reduced to one draw call.
7746
7747         rsurface.batchmultidraw = false;
7748         rsurface.batchmultidrawnumsurfaces = 0;
7749         rsurface.batchmultidrawsurfacelist = NULL;
7750
7751         if (!dynamicvertex)
7752         {
7753                 // static vertex data, just set pointers...
7754                 rsurface.batchgeneratedvertex = false;
7755                 // if there are gaps, we want to build a combined index buffer,
7756                 // otherwise use the original static buffer with an appropriate offset
7757                 if (gaps)
7758                 {
7759                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
7760                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
7761                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
7762                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
7763                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
7764                         {
7765                                 rsurface.batchmultidraw = true;
7766                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
7767                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
7768                                 return;
7769                         }
7770                         // build a new triangle elements array for this batch
7771                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7772                         rsurface.batchfirsttriangle = 0;
7773                         numtriangles = 0;
7774                         for (i = 0;i < texturenumsurfaces;i++)
7775                         {
7776                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7777                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7778                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
7779                                 numtriangles += surfacenumtriangles;
7780                         }
7781                         rsurface.batchelement3i_indexbuffer = NULL;
7782                         rsurface.batchelement3i_bufferoffset = 0;
7783                         rsurface.batchelement3s = NULL;
7784                         rsurface.batchelement3s_indexbuffer = NULL;
7785                         rsurface.batchelement3s_bufferoffset = 0;
7786                         if (endvertex <= 65536)
7787                         {
7788                                 // make a 16bit (unsigned short) index array if possible
7789                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7790                                 for (i = 0;i < numtriangles*3;i++)
7791                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7792                         }
7793                 }
7794                 else
7795                 {
7796                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
7797                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
7798                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
7799                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
7800                 }
7801                 return;
7802         }
7803
7804         // something needs software processing, do it for real...
7805         // we only directly handle separate array data in this case and then
7806         // generate interleaved data if needed...
7807         rsurface.batchgeneratedvertex = true;
7808         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
7809         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
7810         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
7811         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
7812
7813         // now copy the vertex data into a combined array and make an index array
7814         // (this is what Quake3 does all the time)
7815         // we also apply any skeletal animation here that would have been done in
7816         // the vertex shader, because most of the dynamic vertex animation cases
7817         // need actual vertex positions and normals
7818         //if (dynamicvertex)
7819         {
7820                 rsurface.batchvertex3f = NULL;
7821                 rsurface.batchvertex3f_vertexbuffer = NULL;
7822                 rsurface.batchvertex3f_bufferoffset = 0;
7823                 rsurface.batchsvector3f = NULL;
7824                 rsurface.batchsvector3f_vertexbuffer = NULL;
7825                 rsurface.batchsvector3f_bufferoffset = 0;
7826                 rsurface.batchtvector3f = NULL;
7827                 rsurface.batchtvector3f_vertexbuffer = NULL;
7828                 rsurface.batchtvector3f_bufferoffset = 0;
7829                 rsurface.batchnormal3f = NULL;
7830                 rsurface.batchnormal3f_vertexbuffer = NULL;
7831                 rsurface.batchnormal3f_bufferoffset = 0;
7832                 rsurface.batchlightmapcolor4f = NULL;
7833                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7834                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7835                 rsurface.batchtexcoordtexture2f = NULL;
7836                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7837                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7838                 rsurface.batchtexcoordlightmap2f = NULL;
7839                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7840                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7841                 rsurface.batchskeletalindex4ub = NULL;
7842                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7843                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
7844                 rsurface.batchskeletalweight4ub = NULL;
7845                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7846                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
7847                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7848                 rsurface.batchelement3i_indexbuffer = NULL;
7849                 rsurface.batchelement3i_bufferoffset = 0;
7850                 rsurface.batchelement3s = NULL;
7851                 rsurface.batchelement3s_indexbuffer = NULL;
7852                 rsurface.batchelement3s_bufferoffset = 0;
7853                 rsurface.batchskeletaltransform3x4buffer = NULL;
7854                 rsurface.batchskeletaltransform3x4offset = 0;
7855                 rsurface.batchskeletaltransform3x4size = 0;
7856                 // we'll only be setting up certain arrays as needed
7857                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7858                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7859                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7860                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7861                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7862                 {
7863                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7864                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7865                 }
7866                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7867                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
7868                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7869                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7870                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7871                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7872                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7873                 {
7874                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7875                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7876                 }
7877                 numvertices = 0;
7878                 numtriangles = 0;
7879                 for (i = 0;i < texturenumsurfaces;i++)
7880                 {
7881                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
7882                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
7883                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7884                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7885                         // copy only the data requested
7886                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
7887                         {
7888                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7889                                 {
7890                                         if (rsurface.batchvertex3f)
7891                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7892                                         else
7893                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7894                                 }
7895                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7896                                 {
7897                                         if (rsurface.modelnormal3f)
7898                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7899                                         else
7900                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7901                                 }
7902                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7903                                 {
7904                                         if (rsurface.modelsvector3f)
7905                                         {
7906                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7907                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7908                                         }
7909                                         else
7910                                         {
7911                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7912                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7913                                         }
7914                                 }
7915                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7916                                 {
7917                                         if (rsurface.modellightmapcolor4f)
7918                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
7919                                         else
7920                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
7921                                 }
7922                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7923                                 {
7924                                         if (rsurface.modeltexcoordtexture2f)
7925                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7926                                         else
7927                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7928                                 }
7929                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7930                                 {
7931                                         if (rsurface.modeltexcoordlightmap2f)
7932                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7933                                         else
7934                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7935                                 }
7936                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7937                                 {
7938                                         if (rsurface.modelskeletalindex4ub)
7939                                         {
7940                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7941                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7942                                         }
7943                                         else
7944                                         {
7945                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7946                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7947                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
7948                                                 for (j = 0;j < surfacenumvertices;j++)
7949                                                         ub[j*4] = 255;
7950                                         }
7951                                 }
7952                         }
7953                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
7954                         numvertices += surfacenumvertices;
7955                         numtriangles += surfacenumtriangles;
7956                 }
7957
7958                 // generate a 16bit index array as well if possible
7959                 // (in general, dynamic batches fit)
7960                 if (numvertices <= 65536)
7961                 {
7962                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7963                         for (i = 0;i < numtriangles*3;i++)
7964                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7965                 }
7966
7967                 // since we've copied everything, the batch now starts at 0
7968                 rsurface.batchfirstvertex = 0;
7969                 rsurface.batchnumvertices = batchnumvertices;
7970                 rsurface.batchfirsttriangle = 0;
7971                 rsurface.batchnumtriangles = batchnumtriangles;
7972         }
7973
7974         // apply skeletal animation that would have been done in the vertex shader
7975         if (rsurface.batchskeletaltransform3x4)
7976         {
7977                 const unsigned char *si;
7978                 const unsigned char *sw;
7979                 const float *t[4];
7980                 const float *b = rsurface.batchskeletaltransform3x4;
7981                 float *vp, *vs, *vt, *vn;
7982                 float w[4];
7983                 float m[3][4], n[3][4];
7984                 float tp[3], ts[3], tt[3], tn[3];
7985                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
7986                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
7987                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
7988                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
7989                 si = rsurface.batchskeletalindex4ub;
7990                 sw = rsurface.batchskeletalweight4ub;
7991                 vp = rsurface.batchvertex3f;
7992                 vs = rsurface.batchsvector3f;
7993                 vt = rsurface.batchtvector3f;
7994                 vn = rsurface.batchnormal3f;
7995                 memset(m[0], 0, sizeof(m));
7996                 memset(n[0], 0, sizeof(n));
7997                 for (i = 0;i < batchnumvertices;i++)
7998                 {
7999                         t[0] = b + si[0]*12;
8000                         if (sw[0] == 255)
8001                         {
8002                                 // common case - only one matrix
8003                                 m[0][0] = t[0][ 0];
8004                                 m[0][1] = t[0][ 1];
8005                                 m[0][2] = t[0][ 2];
8006                                 m[0][3] = t[0][ 3];
8007                                 m[1][0] = t[0][ 4];
8008                                 m[1][1] = t[0][ 5];
8009                                 m[1][2] = t[0][ 6];
8010                                 m[1][3] = t[0][ 7];
8011                                 m[2][0] = t[0][ 8];
8012                                 m[2][1] = t[0][ 9];
8013                                 m[2][2] = t[0][10];
8014                                 m[2][3] = t[0][11];
8015                         }
8016                         else if (sw[2] + sw[3])
8017                         {
8018                                 // blend 4 matrices
8019                                 t[1] = b + si[1]*12;
8020                                 t[2] = b + si[2]*12;
8021                                 t[3] = b + si[3]*12;
8022                                 w[0] = sw[0] * (1.0f / 255.0f);
8023                                 w[1] = sw[1] * (1.0f / 255.0f);
8024                                 w[2] = sw[2] * (1.0f / 255.0f);
8025                                 w[3] = sw[3] * (1.0f / 255.0f);
8026                                 // blend the matrices
8027                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
8028                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
8029                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
8030                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
8031                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
8032                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
8033                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
8034                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
8035                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
8036                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
8037                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
8038                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
8039                         }
8040                         else
8041                         {
8042                                 // blend 2 matrices
8043                                 t[1] = b + si[1]*12;
8044                                 w[0] = sw[0] * (1.0f / 255.0f);
8045                                 w[1] = sw[1] * (1.0f / 255.0f);
8046                                 // blend the matrices
8047                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
8048                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
8049                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
8050                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
8051                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
8052                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
8053                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
8054                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
8055                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
8056                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
8057                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
8058                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
8059                         }
8060                         si += 4;
8061                         sw += 4;
8062                         // modify the vertex
8063                         VectorCopy(vp, tp);
8064                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
8065                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
8066                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
8067                         vp += 3;
8068                         if (vn)
8069                         {
8070                                 // the normal transformation matrix is a set of cross products...
8071                                 CrossProduct(m[1], m[2], n[0]);
8072                                 CrossProduct(m[2], m[0], n[1]);
8073                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
8074                                 VectorCopy(vn, tn);
8075                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
8076                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
8077                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
8078                                 VectorNormalize(vn);
8079                                 vn += 3;
8080                                 if (vs)
8081                                 {
8082                                         VectorCopy(vs, ts);
8083                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
8084                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
8085                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
8086                                         VectorNormalize(vs);
8087                                         vs += 3;
8088                                         VectorCopy(vt, tt);
8089                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
8090                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
8091                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
8092                                         VectorNormalize(vt);
8093                                         vt += 3;
8094                                 }
8095                         }
8096                 }
8097                 rsurface.batchskeletaltransform3x4 = NULL;
8098                 rsurface.batchskeletalnumtransforms = 0;
8099         }
8100
8101         // q1bsp surfaces rendered in vertex color mode have to have colors
8102         // calculated based on lightstyles
8103         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
8104         {
8105                 // generate color arrays for the surfaces in this list
8106                 int c[4];
8107                 int scale;
8108                 int size3;
8109                 const int *offsets;
8110                 const unsigned char *lm;
8111                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8112                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8113                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8114                 numvertices = 0;
8115                 for (i = 0;i < texturenumsurfaces;i++)
8116                 {
8117                         surface = texturesurfacelist[i];
8118                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8119                         surfacenumvertices = surface->num_vertices;
8120                         if (surface->lightmapinfo->samples)
8121                         {
8122                                 for (j = 0;j < surfacenumvertices;j++)
8123                                 {
8124                                         lm = surface->lightmapinfo->samples + offsets[j];
8125                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8126                                         VectorScale(lm, scale, c);
8127                                         if (surface->lightmapinfo->styles[1] != 255)
8128                                         {
8129                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8130                                                 lm += size3;
8131                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8132                                                 VectorMA(c, scale, lm, c);
8133                                                 if (surface->lightmapinfo->styles[2] != 255)
8134                                                 {
8135                                                         lm += size3;
8136                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8137                                                         VectorMA(c, scale, lm, c);
8138                                                         if (surface->lightmapinfo->styles[3] != 255)
8139                                                         {
8140                                                                 lm += size3;
8141                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8142                                                                 VectorMA(c, scale, lm, c);
8143                                                         }
8144                                                 }
8145                                         }
8146                                         c[0] >>= 7;
8147                                         c[1] >>= 7;
8148                                         c[2] >>= 7;
8149                                         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);
8150                                         numvertices++;
8151                                 }
8152                         }
8153                         else
8154                         {
8155                                 for (j = 0;j < surfacenumvertices;j++)
8156                                 {
8157                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8158                                         numvertices++;
8159                                 }
8160                         }
8161                 }
8162         }
8163
8164         // if vertices are deformed (sprite flares and things in maps, possibly
8165         // water waves, bulges and other deformations), modify the copied vertices
8166         // in place
8167         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8168         {
8169                 float scale;
8170                 switch (deform->deform)
8171                 {
8172                 default:
8173                 case Q3DEFORM_PROJECTIONSHADOW:
8174                 case Q3DEFORM_TEXT0:
8175                 case Q3DEFORM_TEXT1:
8176                 case Q3DEFORM_TEXT2:
8177                 case Q3DEFORM_TEXT3:
8178                 case Q3DEFORM_TEXT4:
8179                 case Q3DEFORM_TEXT5:
8180                 case Q3DEFORM_TEXT6:
8181                 case Q3DEFORM_TEXT7:
8182                 case Q3DEFORM_NONE:
8183                         break;
8184                 case Q3DEFORM_AUTOSPRITE:
8185                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8186                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8187                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8188                         VectorNormalize(newforward);
8189                         VectorNormalize(newright);
8190                         VectorNormalize(newup);
8191 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8192 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8193 //                      rsurface.batchvertex3f_bufferoffset = 0;
8194 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8195 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8196 //                      rsurface.batchsvector3f_bufferoffset = 0;
8197 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8198 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8199 //                      rsurface.batchtvector3f_bufferoffset = 0;
8200 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8201 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8202 //                      rsurface.batchnormal3f_bufferoffset = 0;
8203                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8204                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8205                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8206                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8207                                 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);
8208                         // a single autosprite surface can contain multiple sprites...
8209                         for (j = 0;j < batchnumvertices - 3;j += 4)
8210                         {
8211                                 VectorClear(center);
8212                                 for (i = 0;i < 4;i++)
8213                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8214                                 VectorScale(center, 0.25f, center);
8215                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8216                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8217                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8218                                 for (i = 0;i < 4;i++)
8219                                 {
8220                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8221                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8222                                 }
8223                         }
8224                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8225                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8226                         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);
8227                         break;
8228                 case Q3DEFORM_AUTOSPRITE2:
8229                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8230                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8231                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8232                         VectorNormalize(newforward);
8233                         VectorNormalize(newright);
8234                         VectorNormalize(newup);
8235 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8236 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8237 //                      rsurface.batchvertex3f_bufferoffset = 0;
8238                         {
8239                                 const float *v1, *v2;
8240                                 vec3_t start, end;
8241                                 float f, l;
8242                                 struct
8243                                 {
8244                                         float length2;
8245                                         const float *v1;
8246                                         const float *v2;
8247                                 }
8248                                 shortest[2];
8249                                 memset(shortest, 0, sizeof(shortest));
8250                                 // a single autosprite surface can contain multiple sprites...
8251                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8252                                 {
8253                                         VectorClear(center);
8254                                         for (i = 0;i < 4;i++)
8255                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8256                                         VectorScale(center, 0.25f, center);
8257                                         // find the two shortest edges, then use them to define the
8258                                         // axis vectors for rotating around the central axis
8259                                         for (i = 0;i < 6;i++)
8260                                         {
8261                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8262                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8263                                                 l = VectorDistance2(v1, v2);
8264                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8265                                                 if (v1[2] != v2[2])
8266                                                         l += (1.0f / 1024.0f);
8267                                                 if (shortest[0].length2 > l || i == 0)
8268                                                 {
8269                                                         shortest[1] = shortest[0];
8270                                                         shortest[0].length2 = l;
8271                                                         shortest[0].v1 = v1;
8272                                                         shortest[0].v2 = v2;
8273                                                 }
8274                                                 else if (shortest[1].length2 > l || i == 1)
8275                                                 {
8276                                                         shortest[1].length2 = l;
8277                                                         shortest[1].v1 = v1;
8278                                                         shortest[1].v2 = v2;
8279                                                 }
8280                                         }
8281                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8282                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8283                                         // this calculates the right vector from the shortest edge
8284                                         // and the up vector from the edge midpoints
8285                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8286                                         VectorNormalize(right);
8287                                         VectorSubtract(end, start, up);
8288                                         VectorNormalize(up);
8289                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8290                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8291                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8292                                         VectorNegate(forward, forward);
8293                                         VectorReflect(forward, 0, up, forward);
8294                                         VectorNormalize(forward);
8295                                         CrossProduct(up, forward, newright);
8296                                         VectorNormalize(newright);
8297                                         // rotate the quad around the up axis vector, this is made
8298                                         // especially easy by the fact we know the quad is flat,
8299                                         // so we only have to subtract the center position and
8300                                         // measure distance along the right vector, and then
8301                                         // multiply that by the newright vector and add back the
8302                                         // center position
8303                                         // we also need to subtract the old position to undo the
8304                                         // displacement from the center, which we do with a
8305                                         // DotProduct, the subtraction/addition of center is also
8306                                         // optimized into DotProducts here
8307                                         l = DotProduct(right, center);
8308                                         for (i = 0;i < 4;i++)
8309                                         {
8310                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8311                                                 f = DotProduct(right, v1) - l;
8312                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8313                                         }
8314                                 }
8315                         }
8316                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8317                         {
8318 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8319 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8320 //                              rsurface.batchnormal3f_bufferoffset = 0;
8321                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8322                         }
8323                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8324                         {
8325 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8326 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8327 //                              rsurface.batchsvector3f_bufferoffset = 0;
8328 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8329 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8330 //                              rsurface.batchtvector3f_bufferoffset = 0;
8331                                 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);
8332                         }
8333                         break;
8334                 case Q3DEFORM_NORMAL:
8335                         // deform the normals to make reflections wavey
8336                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8337                         rsurface.batchnormal3f_vertexbuffer = NULL;
8338                         rsurface.batchnormal3f_bufferoffset = 0;
8339                         for (j = 0;j < batchnumvertices;j++)
8340                         {
8341                                 float vertex[3];
8342                                 float *normal = rsurface.batchnormal3f + 3*j;
8343                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8344                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8345                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8346                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8347                                 VectorNormalize(normal);
8348                         }
8349                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8350                         {
8351 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8352 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8353 //                              rsurface.batchsvector3f_bufferoffset = 0;
8354 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8355 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8356 //                              rsurface.batchtvector3f_bufferoffset = 0;
8357                                 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);
8358                         }
8359                         break;
8360                 case Q3DEFORM_WAVE:
8361                         // deform vertex array to make wavey water and flags and such
8362                         waveparms[0] = deform->waveparms[0];
8363                         waveparms[1] = deform->waveparms[1];
8364                         waveparms[2] = deform->waveparms[2];
8365                         waveparms[3] = deform->waveparms[3];
8366                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8367                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8368                         // this is how a divisor of vertex influence on deformation
8369                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8370                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8371 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8372 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8373 //                      rsurface.batchvertex3f_bufferoffset = 0;
8374 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8375 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8376 //                      rsurface.batchnormal3f_bufferoffset = 0;
8377                         for (j = 0;j < batchnumvertices;j++)
8378                         {
8379                                 // if the wavefunc depends on time, evaluate it per-vertex
8380                                 if (waveparms[3])
8381                                 {
8382                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8383                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8384                                 }
8385                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8386                         }
8387                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8388                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8389                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8390                         {
8391 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8392 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8393 //                              rsurface.batchsvector3f_bufferoffset = 0;
8394 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8395 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8396 //                              rsurface.batchtvector3f_bufferoffset = 0;
8397                                 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);
8398                         }
8399                         break;
8400                 case Q3DEFORM_BULGE:
8401                         // deform vertex array to make the surface have moving bulges
8402 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8403 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8404 //                      rsurface.batchvertex3f_bufferoffset = 0;
8405 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8406 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8407 //                      rsurface.batchnormal3f_bufferoffset = 0;
8408                         for (j = 0;j < batchnumvertices;j++)
8409                         {
8410                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8411                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8412                         }
8413                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8414                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8415                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8416                         {
8417 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8418 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8419 //                              rsurface.batchsvector3f_bufferoffset = 0;
8420 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8421 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8422 //                              rsurface.batchtvector3f_bufferoffset = 0;
8423                                 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);
8424                         }
8425                         break;
8426                 case Q3DEFORM_MOVE:
8427                         // deform vertex array
8428                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8429                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8430                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8431                         VectorScale(deform->parms, scale, waveparms);
8432 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8433 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8434 //                      rsurface.batchvertex3f_bufferoffset = 0;
8435                         for (j = 0;j < batchnumvertices;j++)
8436                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8437                         break;
8438                 }
8439         }
8440
8441         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
8442         {
8443         // generate texcoords based on the chosen texcoord source
8444                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
8445                 {
8446                 default:
8447                 case Q3TCGEN_TEXTURE:
8448                         break;
8449                 case Q3TCGEN_LIGHTMAP:
8450         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8451         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8452         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8453                         if (rsurface.batchtexcoordlightmap2f)
8454                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
8455                         break;
8456                 case Q3TCGEN_VECTOR:
8457         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8458         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8459         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8460                         for (j = 0;j < batchnumvertices;j++)
8461                         {
8462                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
8463                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
8464                         }
8465                         break;
8466                 case Q3TCGEN_ENVIRONMENT:
8467                         // make environment reflections using a spheremap
8468                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8469                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8470                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8471                         for (j = 0;j < batchnumvertices;j++)
8472                         {
8473                                 // identical to Q3A's method, but executed in worldspace so
8474                                 // carried models can be shiny too
8475
8476                                 float viewer[3], d, reflected[3], worldreflected[3];
8477
8478                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8479                                 // VectorNormalize(viewer);
8480
8481                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8482
8483                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8484                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8485                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8486                                 // note: this is proportinal to viewer, so we can normalize later
8487
8488                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8489                                 VectorNormalize(worldreflected);
8490
8491                                 // note: this sphere map only uses world x and z!
8492                                 // so positive and negative y will LOOK THE SAME.
8493                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8494                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8495                         }
8496                         break;
8497                 }
8498                 // the only tcmod that needs software vertex processing is turbulent, so
8499                 // check for it here and apply the changes if needed
8500                 // and we only support that as the first one
8501                 // (handling a mixture of turbulent and other tcmods would be problematic
8502                 //  without punting it entirely to a software path)
8503                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8504                 {
8505                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
8506                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
8507         //              rsurface.batchtexcoordtexture2f = 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                                 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);
8513                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8514                         }
8515                 }
8516         }
8517 }
8518
8519 void RSurf_DrawBatch(void)
8520 {
8521         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8522         // through the pipeline, killing it earlier in the pipeline would have
8523         // per-surface overhead rather than per-batch overhead, so it's best to
8524         // reject it here, before it hits glDraw.
8525         if (rsurface.batchnumtriangles == 0)
8526                 return;
8527 #if 0
8528         // batch debugging code
8529         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8530         {
8531                 int i;
8532                 int j;
8533                 int c;
8534                 const int *e;
8535                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8536                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8537                 {
8538                         c = e[i];
8539                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8540                         {
8541                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8542                                 {
8543                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8544                                                 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);
8545                                         break;
8546                                 }
8547                         }
8548                 }
8549         }
8550 #endif
8551         if (rsurface.batchmultidraw)
8552         {
8553                 // issue multiple draws rather than copying index data
8554                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
8555                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
8556                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
8557                 for (i = 0;i < numsurfaces;)
8558                 {
8559                         // combine consecutive surfaces as one draw
8560                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
8561                                 if (surfacelist[j] != surfacelist[k] + 1)
8562                                         break;
8563                         firstvertex = surfacelist[i]->num_firstvertex;
8564                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
8565                         firsttriangle = surfacelist[i]->num_firsttriangle;
8566                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
8567                         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);
8568                         i = j;
8569                 }
8570         }
8571         else
8572         {
8573                 // there is only one consecutive run of index data (may have been combined)
8574                 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);
8575         }
8576 }
8577
8578 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8579 {
8580         // pick the closest matching water plane
8581         int planeindex, vertexindex, bestplaneindex = -1;
8582         float d, bestd;
8583         vec3_t vert;
8584         const float *v;
8585         r_waterstate_waterplane_t *p;
8586         qboolean prepared = false;
8587         bestd = 0;
8588         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
8589         {
8590                 if(p->camera_entity != rsurface.texture->camera_entity)
8591                         continue;
8592                 d = 0;
8593                 if(!prepared)
8594                 {
8595                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
8596                         prepared = true;
8597                         if(rsurface.batchnumvertices == 0)
8598                                 break;
8599                 }
8600                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8601                 {
8602                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8603                         d += fabs(PlaneDiff(vert, &p->plane));
8604                 }
8605                 if (bestd > d || bestplaneindex < 0)
8606                 {
8607                         bestd = d;
8608                         bestplaneindex = planeindex;
8609                 }
8610         }
8611         return bestplaneindex;
8612         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8613         // this situation though, as it might be better to render single larger
8614         // batches with useless stuff (backface culled for example) than to
8615         // render multiple smaller batches
8616 }
8617
8618 void RSurf_SetupDepthAndCulling(void)
8619 {
8620         // submodels are biased to avoid z-fighting with world surfaces that they
8621         // may be exactly overlapping (avoids z-fighting artifacts on certain
8622         // doors and things in Quake maps)
8623         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8624         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8625         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8626         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8627 }
8628
8629 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8630 {
8631         int i, j;
8632         // transparent sky would be ridiculous
8633         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8634                 return;
8635         R_SetupShader_Generic_NoTexture(false, false);
8636         skyrenderlater = true;
8637         RSurf_SetupDepthAndCulling();
8638         GL_DepthMask(true);
8639
8640         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
8641         if (r_sky_scissor.integer)
8642         {
8643                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8644                 for (i = 0; i < texturenumsurfaces; i++)
8645                 {
8646                         const msurface_t *surf = texturesurfacelist[i];
8647                         const float *v;
8648                         float p[3];
8649                         float mins[3], maxs[3];
8650                         int scissor[4];
8651                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
8652                         {
8653                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
8654                                 if (j > 0)
8655                                 {
8656                                         if (mins[0] > p[0]) mins[0] = p[0];
8657                                         if (mins[1] > p[1]) mins[1] = p[1];
8658                                         if (mins[2] > p[2]) mins[2] = p[2];
8659                                         if (maxs[0] < p[0]) maxs[0] = p[0];
8660                                         if (maxs[1] < p[1]) maxs[1] = p[1];
8661                                         if (maxs[2] < p[2]) maxs[2] = p[2];
8662                                 }
8663                                 else
8664                                 {
8665                                         VectorCopy(p, mins);
8666                                         VectorCopy(p, maxs);
8667                                 }
8668                         }
8669                         if (!R_ScissorForBBox(mins, maxs, scissor))
8670                         {
8671                                 if (skyscissor[2])
8672                                 {
8673                                         if (skyscissor[0] > scissor[0])
8674                                         {
8675                                                 skyscissor[2] += skyscissor[0] - scissor[0];
8676                                                 skyscissor[0] = scissor[0];
8677                                         }
8678                                         if (skyscissor[1] > scissor[1])
8679                                         {
8680                                                 skyscissor[3] += skyscissor[1] - scissor[1];
8681                                                 skyscissor[1] = scissor[1];
8682                                         }
8683                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
8684                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
8685                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
8686                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
8687                                 }
8688                                 else
8689                                         Vector4Copy(scissor, skyscissor);
8690                         }
8691                 }
8692         }
8693
8694         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
8695         // skymasking on them, and Quake3 never did sky masking (unlike
8696         // software Quake and software Quake2), so disable the sky masking
8697         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8698         // and skymasking also looks very bad when noclipping outside the
8699         // level, so don't use it then either.
8700         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)
8701         {
8702                 R_Mesh_ResetTextureState();
8703                 if (skyrendermasked)
8704                 {
8705                         R_SetupShader_DepthOrShadow(false, false, false);
8706                         // depth-only (masking)
8707                         GL_ColorMask(0, 0, 0, 0);
8708                         // just to make sure that braindead drivers don't draw
8709                         // anything despite that colormask...
8710                         GL_BlendFunc(GL_ZERO, GL_ONE);
8711                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8712                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8713                 }
8714                 else
8715                 {
8716                         R_SetupShader_Generic_NoTexture(false, false);
8717                         // fog sky
8718                         GL_BlendFunc(GL_ONE, GL_ZERO);
8719                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
8720                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8721                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
8722                 }
8723                 RSurf_DrawBatch();
8724                 if (skyrendermasked)
8725                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8726         }
8727         R_Mesh_ResetTextureState();
8728         GL_Color(1, 1, 1, 1);
8729 }
8730
8731 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8732 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8733 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8734 {
8735         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
8736                 return;
8737         if (prepass)
8738         {
8739                 // render screenspace normalmap to texture
8740                 GL_DepthMask(true);
8741                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
8742                 RSurf_DrawBatch();
8743                 return;
8744         }
8745
8746         // bind lightmap texture
8747
8748         // water/refraction/reflection/camera surfaces have to be handled specially
8749         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
8750         {
8751                 int start, end, startplaneindex;
8752                 for (start = 0;start < texturenumsurfaces;start = end)
8753                 {
8754                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
8755                         if(startplaneindex < 0)
8756                         {
8757                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
8758                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
8759                                 end = start + 1;
8760                                 continue;
8761                         }
8762                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
8763                                 ;
8764                         // now that we have a batch using the same planeindex, render it
8765                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
8766                         {
8767                                 // render water or distortion background
8768                                 GL_DepthMask(true);
8769                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8770                                 RSurf_DrawBatch();
8771                                 // blend surface on top
8772                                 GL_DepthMask(false);
8773                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
8774                                 RSurf_DrawBatch();
8775                         }
8776                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
8777                         {
8778                                 // render surface with reflection texture as input
8779                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8780                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8781                                 RSurf_DrawBatch();
8782                         }
8783                 }
8784                 return;
8785         }
8786
8787         // render surface batch normally
8788         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8789         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
8790         RSurf_DrawBatch();
8791 }
8792
8793 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8794 {
8795         int vi;
8796         int j;
8797         int texturesurfaceindex;
8798         int k;
8799         const msurface_t *surface;
8800         float surfacecolor4f[4];
8801
8802 //      R_Mesh_ResetTextureState();
8803         R_SetupShader_Generic_NoTexture(false, false);
8804
8805         GL_BlendFunc(GL_ONE, GL_ZERO);
8806         GL_DepthMask(writedepth);
8807
8808         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
8809         vi = 0;
8810         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8811         {
8812                 surface = texturesurfacelist[texturesurfaceindex];
8813                 k = (int)(((size_t)surface) / sizeof(msurface_t));
8814                 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
8815                 for (j = 0;j < surface->num_vertices;j++)
8816                 {
8817                         Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
8818                         vi++;
8819                 }
8820         }
8821         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f);
8822         RSurf_DrawBatch();
8823 }
8824
8825 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8826 {
8827         CHECKGLERROR
8828         RSurf_SetupDepthAndCulling();
8829         if (r_showsurfaces.integer && r_refdef.view.showdebug)
8830         {
8831                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
8832                 return;
8833         }
8834         switch (vid.renderpath)
8835         {
8836         case RENDERPATH_GL32:
8837         case RENDERPATH_GLES2:
8838                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8839                 break;
8840         }
8841         CHECKGLERROR
8842 }
8843
8844 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8845 {
8846         int i, j;
8847         int texturenumsurfaces, endsurface;
8848         texture_t *texture;
8849         const msurface_t *surface;
8850         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
8851
8852         RSurf_ActiveModelEntity(ent, true, true, false);
8853
8854         if (r_transparentdepthmasking.integer)
8855         {
8856                 qboolean setup = false;
8857                 for (i = 0;i < numsurfaces;i = j)
8858                 {
8859                         j = i + 1;
8860                         surface = rsurface.modelsurfaces + surfacelist[i];
8861                         texture = surface->texture;
8862                         rsurface.texture = R_GetCurrentTexture(texture);
8863                         rsurface.lightmaptexture = NULL;
8864                         rsurface.deluxemaptexture = NULL;
8865                         rsurface.uselightmaptexture = false;
8866                         // scan ahead until we find a different texture
8867                         endsurface = min(i + 1024, numsurfaces);
8868                         texturenumsurfaces = 0;
8869                         texturesurfacelist[texturenumsurfaces++] = surface;
8870                         for (;j < endsurface;j++)
8871                         {
8872                                 surface = rsurface.modelsurfaces + surfacelist[j];
8873                                 if (texture != surface->texture)
8874                                         break;
8875                                 texturesurfacelist[texturenumsurfaces++] = surface;
8876                         }
8877                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8878                                 continue;
8879                         // render the range of surfaces as depth
8880                         if (!setup)
8881                         {
8882                                 setup = true;
8883                                 GL_ColorMask(0,0,0,0);
8884                                 GL_Color(1,1,1,1);
8885                                 GL_DepthTest(true);
8886                                 GL_BlendFunc(GL_ONE, GL_ZERO);
8887                                 GL_DepthMask(true);
8888 //                              R_Mesh_ResetTextureState();
8889                         }
8890                         RSurf_SetupDepthAndCulling();
8891                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8892                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8893                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8894                         RSurf_DrawBatch();
8895                 }
8896                 if (setup)
8897                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8898         }
8899
8900         for (i = 0;i < numsurfaces;i = j)
8901         {
8902                 j = i + 1;
8903                 surface = rsurface.modelsurfaces + surfacelist[i];
8904                 texture = surface->texture;
8905                 rsurface.texture = R_GetCurrentTexture(texture);
8906                 // scan ahead until we find a different texture
8907                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
8908                 texturenumsurfaces = 0;
8909                 texturesurfacelist[texturenumsurfaces++] = surface;
8910                         rsurface.lightmaptexture = surface->lightmaptexture;
8911                         rsurface.deluxemaptexture = surface->deluxemaptexture;
8912                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8913                         for (;j < endsurface;j++)
8914                         {
8915                                 surface = rsurface.modelsurfaces + surfacelist[j];
8916                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
8917                                         break;
8918                                 texturesurfacelist[texturenumsurfaces++] = surface;
8919                         }
8920                 // render the range of surfaces
8921                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8922         }
8923         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
8924 }
8925
8926 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8927 {
8928         // transparent surfaces get pushed off into the transparent queue
8929         int surfacelistindex;
8930         const msurface_t *surface;
8931         vec3_t tempcenter, center;
8932         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8933         {
8934                 surface = texturesurfacelist[surfacelistindex];
8935                 if (r_transparent_sortsurfacesbynearest.integer)
8936                 {
8937                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
8938                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
8939                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
8940                 }
8941                 else
8942                 {
8943                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8944                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8945                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8946                 }
8947                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8948                 if (rsurface.entity->transparent_offset) // transparent offset
8949                 {
8950                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
8951                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
8952                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
8953                 }
8954                 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);
8955         }
8956 }
8957
8958 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8959 {
8960         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8961                 return;
8962         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8963                 return;
8964         RSurf_SetupDepthAndCulling();
8965         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8966         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8967         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8968         RSurf_DrawBatch();
8969 }
8970
8971 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
8972 {
8973         CHECKGLERROR
8974         if (ui)
8975                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8976         else if (depthonly)
8977                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
8978         else if (prepass)
8979         {
8980                 if (!rsurface.texture->currentnumlayers)
8981                         return;
8982                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8983                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
8984                 else
8985                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8986         }
8987         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
8988                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8989         else if (!rsurface.texture->currentnumlayers)
8990                 return;
8991         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
8992         {
8993                 // in the deferred case, transparent surfaces were queued during prepass
8994                 if (!r_shadow_usingdeferredprepass)
8995                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
8996         }
8997         else
8998         {
8999                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9000                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9001         }
9002         CHECKGLERROR
9003 }
9004
9005 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
9006 {
9007         int i, j;
9008         texture_t *texture;
9009         R_FrameData_SetMark();
9010         // break the surface list down into batches by texture and use of lightmapping
9011         for (i = 0;i < numsurfaces;i = j)
9012         {
9013                 j = i + 1;
9014                 // texture is the base texture pointer, rsurface.texture is the
9015                 // current frame/skin the texture is directing us to use (for example
9016                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9017                 // use skin 1 instead)
9018                 texture = surfacelist[i]->texture;
9019                 rsurface.texture = R_GetCurrentTexture(texture);
9020                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9021                 {
9022                         // if this texture is not the kind we want, skip ahead to the next one
9023                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9024                                 ;
9025                         continue;
9026                 }
9027                 if(depthonly || prepass)
9028                 {
9029                         rsurface.lightmaptexture = NULL;
9030                         rsurface.deluxemaptexture = NULL;
9031                         rsurface.uselightmaptexture = false;
9032                         // simply scan ahead until we find a different texture or lightmap state
9033                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9034                                 ;
9035                 }
9036                 else
9037                 {
9038                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9039                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9040                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9041                         // simply scan ahead until we find a different texture or lightmap state
9042                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9043                                 ;
9044                 }
9045                 // render the range of surfaces
9046                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass, ui);
9047         }
9048         R_FrameData_ReturnToMark();
9049 }
9050
9051 float locboxvertex3f[6*4*3] =
9052 {
9053         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9054         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9055         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9056         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9057         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9058         1,0,0, 0,0,0, 0,1,0, 1,1,0
9059 };
9060
9061 unsigned short locboxelements[6*2*3] =
9062 {
9063          0, 1, 2, 0, 2, 3,
9064          4, 5, 6, 4, 6, 7,
9065          8, 9,10, 8,10,11,
9066         12,13,14, 12,14,15,
9067         16,17,18, 16,18,19,
9068         20,21,22, 20,22,23
9069 };
9070
9071 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9072 {
9073         int i, j;
9074         cl_locnode_t *loc = (cl_locnode_t *)ent;
9075         vec3_t mins, size;
9076         float vertex3f[6*4*3];
9077         CHECKGLERROR
9078         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9079         GL_DepthMask(false);
9080         GL_DepthRange(0, 1);
9081         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9082         GL_DepthTest(true);
9083         GL_CullFace(GL_NONE);
9084         R_EntityMatrix(&identitymatrix);
9085
9086 //      R_Mesh_ResetTextureState();
9087
9088         i = surfacelist[0];
9089         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9090                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9091                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9092                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9093
9094         if (VectorCompare(loc->mins, loc->maxs))
9095         {
9096                 VectorSet(size, 2, 2, 2);
9097                 VectorMA(loc->mins, -0.5f, size, mins);
9098         }
9099         else
9100         {
9101                 VectorCopy(loc->mins, mins);
9102                 VectorSubtract(loc->maxs, loc->mins, size);
9103         }
9104
9105         for (i = 0;i < 6*4*3;)
9106                 for (j = 0;j < 3;j++, i++)
9107                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9108
9109         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
9110         R_SetupShader_Generic_NoTexture(false, false);
9111         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
9112 }
9113
9114 void R_DrawLocs(void)
9115 {
9116         int index;
9117         cl_locnode_t *loc, *nearestloc;
9118         vec3_t center;
9119         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9120         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9121         {
9122                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9123                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9124         }
9125 }
9126
9127 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9128 {
9129         if (decalsystem->decals)
9130                 Mem_Free(decalsystem->decals);
9131         memset(decalsystem, 0, sizeof(*decalsystem));
9132 }
9133
9134 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)
9135 {
9136         tridecal_t *decal;
9137         tridecal_t *decals;
9138         int i;
9139
9140         // expand or initialize the system
9141         if (decalsystem->maxdecals <= decalsystem->numdecals)
9142         {
9143                 decalsystem_t old = *decalsystem;
9144                 qboolean useshortelements;
9145                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9146                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9147                 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)));
9148                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9149                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9150                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9151                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9152                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9153                 if (decalsystem->numdecals)
9154                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9155                 if (old.decals)
9156                         Mem_Free(old.decals);
9157                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9158                         decalsystem->element3i[i] = i;
9159                 if (useshortelements)
9160                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9161                                 decalsystem->element3s[i] = i;
9162         }
9163
9164         // grab a decal and search for another free slot for the next one
9165         decals = decalsystem->decals;
9166         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9167         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
9168                 ;
9169         decalsystem->freedecal = i;
9170         if (decalsystem->numdecals <= i)
9171                 decalsystem->numdecals = i + 1;
9172
9173         // initialize the decal
9174         decal->lived = 0;
9175         decal->triangleindex = triangleindex;
9176         decal->surfaceindex = surfaceindex;
9177         decal->decalsequence = decalsequence;
9178         decal->color4f[0][0] = c0[0];
9179         decal->color4f[0][1] = c0[1];
9180         decal->color4f[0][2] = c0[2];
9181         decal->color4f[0][3] = 1;
9182         decal->color4f[1][0] = c1[0];
9183         decal->color4f[1][1] = c1[1];
9184         decal->color4f[1][2] = c1[2];
9185         decal->color4f[1][3] = 1;
9186         decal->color4f[2][0] = c2[0];
9187         decal->color4f[2][1] = c2[1];
9188         decal->color4f[2][2] = c2[2];
9189         decal->color4f[2][3] = 1;
9190         decal->vertex3f[0][0] = v0[0];
9191         decal->vertex3f[0][1] = v0[1];
9192         decal->vertex3f[0][2] = v0[2];
9193         decal->vertex3f[1][0] = v1[0];
9194         decal->vertex3f[1][1] = v1[1];
9195         decal->vertex3f[1][2] = v1[2];
9196         decal->vertex3f[2][0] = v2[0];
9197         decal->vertex3f[2][1] = v2[1];
9198         decal->vertex3f[2][2] = v2[2];
9199         decal->texcoord2f[0][0] = t0[0];
9200         decal->texcoord2f[0][1] = t0[1];
9201         decal->texcoord2f[1][0] = t1[0];
9202         decal->texcoord2f[1][1] = t1[1];
9203         decal->texcoord2f[2][0] = t2[0];
9204         decal->texcoord2f[2][1] = t2[1];
9205         TriangleNormal(v0, v1, v2, decal->plane);
9206         VectorNormalize(decal->plane);
9207         decal->plane[3] = DotProduct(v0, decal->plane);
9208 }
9209
9210 extern cvar_t cl_decals_bias;
9211 extern cvar_t cl_decals_models;
9212 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9213 // baseparms, parms, temps
9214 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)
9215 {
9216         int cornerindex;
9217         int index;
9218         float v[9][3];
9219         const float *vertex3f;
9220         const float *normal3f;
9221         int numpoints;
9222         float points[2][9][3];
9223         float temp[3];
9224         float tc[9][2];
9225         float f;
9226         float c[9][4];
9227         const int *e;
9228
9229         e = rsurface.modelelement3i + 3*triangleindex;
9230
9231         vertex3f = rsurface.modelvertex3f;
9232         normal3f = rsurface.modelnormal3f;
9233
9234         if (normal3f)
9235         {
9236                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9237                 {
9238                         index = 3*e[cornerindex];
9239                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
9240                 }
9241         }
9242         else
9243         {
9244                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9245                 {
9246                         index = 3*e[cornerindex];
9247                         VectorCopy(vertex3f + index, v[cornerindex]);
9248                 }
9249         }
9250
9251         // cull backfaces
9252         //TriangleNormal(v[0], v[1], v[2], normal);
9253         //if (DotProduct(normal, localnormal) < 0.0f)
9254         //      continue;
9255         // clip by each of the box planes formed from the projection matrix
9256         // if anything survives, we emit the decal
9257         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]);
9258         if (numpoints < 3)
9259                 return;
9260         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]);
9261         if (numpoints < 3)
9262                 return;
9263         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]);
9264         if (numpoints < 3)
9265                 return;
9266         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]);
9267         if (numpoints < 3)
9268                 return;
9269         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]);
9270         if (numpoints < 3)
9271                 return;
9272         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]);
9273         if (numpoints < 3)
9274                 return;
9275         // some part of the triangle survived, so we have to accept it...
9276         if (dynamic)
9277         {
9278                 // dynamic always uses the original triangle
9279                 numpoints = 3;
9280                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9281                 {
9282                         index = 3*e[cornerindex];
9283                         VectorCopy(vertex3f + index, v[cornerindex]);
9284                 }
9285         }
9286         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9287         {
9288                 // convert vertex positions to texcoords
9289                 Matrix4x4_Transform(projection, v[cornerindex], temp);
9290                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9291                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9292                 // calculate distance fade from the projection origin
9293                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9294                 f = bound(0.0f, f, 1.0f);
9295                 c[cornerindex][0] = r * f;
9296                 c[cornerindex][1] = g * f;
9297                 c[cornerindex][2] = b * f;
9298                 c[cornerindex][3] = 1.0f;
9299                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9300         }
9301         if (dynamic)
9302                 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);
9303         else
9304                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9305                         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);
9306 }
9307 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)
9308 {
9309         matrix4x4_t projection;
9310         decalsystem_t *decalsystem;
9311         qboolean dynamic;
9312         dp_model_t *model;
9313         const msurface_t *surface;
9314         const msurface_t *surfaces;
9315         const int *surfacelist;
9316         const texture_t *texture;
9317         int numtriangles;
9318         int numsurfacelist;
9319         int surfacelistindex;
9320         int surfaceindex;
9321         int triangleindex;
9322         float localorigin[3];
9323         float localnormal[3];
9324         float localmins[3];
9325         float localmaxs[3];
9326         float localsize;
9327         //float normal[3];
9328         float planes[6][4];
9329         float angles[3];
9330         bih_t *bih;
9331         int bih_triangles_count;
9332         int bih_triangles[256];
9333         int bih_surfaces[256];
9334
9335         decalsystem = &ent->decalsystem;
9336         model = ent->model;
9337         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9338         {
9339                 R_DecalSystem_Reset(&ent->decalsystem);
9340                 return;
9341         }
9342
9343         if (!model->brush.data_leafs && !cl_decals_models.integer)
9344         {
9345                 if (decalsystem->model)
9346                         R_DecalSystem_Reset(decalsystem);
9347                 return;
9348         }
9349
9350         if (decalsystem->model != model)
9351                 R_DecalSystem_Reset(decalsystem);
9352         decalsystem->model = model;
9353
9354         RSurf_ActiveModelEntity(ent, true, false, false);
9355
9356         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9357         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9358         VectorNormalize(localnormal);
9359         localsize = worldsize*rsurface.inversematrixscale;
9360         localmins[0] = localorigin[0] - localsize;
9361         localmins[1] = localorigin[1] - localsize;
9362         localmins[2] = localorigin[2] - localsize;
9363         localmaxs[0] = localorigin[0] + localsize;
9364         localmaxs[1] = localorigin[1] + localsize;
9365         localmaxs[2] = localorigin[2] + localsize;
9366
9367         //VectorCopy(localnormal, planes[4]);
9368         //VectorVectors(planes[4], planes[2], planes[0]);
9369         AnglesFromVectors(angles, localnormal, NULL, false);
9370         AngleVectors(angles, planes[0], planes[2], planes[4]);
9371         VectorNegate(planes[0], planes[1]);
9372         VectorNegate(planes[2], planes[3]);
9373         VectorNegate(planes[4], planes[5]);
9374         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9375         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9376         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9377         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9378         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9379         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9380
9381 #if 1
9382 // works
9383 {
9384         matrix4x4_t forwardprojection;
9385         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9386         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9387 }
9388 #else
9389 // broken
9390 {
9391         float projectionvector[4][3];
9392         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9393         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9394         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9395         projectionvector[0][0] = planes[0][0] * ilocalsize;
9396         projectionvector[0][1] = planes[1][0] * ilocalsize;
9397         projectionvector[0][2] = planes[2][0] * ilocalsize;
9398         projectionvector[1][0] = planes[0][1] * ilocalsize;
9399         projectionvector[1][1] = planes[1][1] * ilocalsize;
9400         projectionvector[1][2] = planes[2][1] * ilocalsize;
9401         projectionvector[2][0] = planes[0][2] * ilocalsize;
9402         projectionvector[2][1] = planes[1][2] * ilocalsize;
9403         projectionvector[2][2] = planes[2][2] * ilocalsize;
9404         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9405         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9406         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9407         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9408 }
9409 #endif
9410
9411         dynamic = model->surfmesh.isanimated;
9412         numsurfacelist = model->nummodelsurfaces;
9413         surfacelist = model->sortedmodelsurfaces;
9414         surfaces = model->data_surfaces;
9415
9416         bih = NULL;
9417         bih_triangles_count = -1;
9418         if(!dynamic)
9419         {
9420                 if(model->render_bih.numleafs)
9421                         bih = &model->render_bih;
9422                 else if(model->collision_bih.numleafs)
9423                         bih = &model->collision_bih;
9424         }
9425         if(bih)
9426                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
9427         if(bih_triangles_count == 0)
9428                 return;
9429         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
9430                 return;
9431         if(bih_triangles_count > 0)
9432         {
9433                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
9434                 {
9435                         surfaceindex = bih_surfaces[triangleindex];
9436                         surface = surfaces + surfaceindex;
9437                         texture = surface->texture;
9438                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9439                                 continue;
9440                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9441                                 continue;
9442                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
9443                 }
9444         }
9445         else
9446         {
9447                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9448                 {
9449                         surfaceindex = surfacelist[surfacelistindex];
9450                         surface = surfaces + surfaceindex;
9451                         // check cull box first because it rejects more than any other check
9452                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9453                                 continue;
9454                         // skip transparent surfaces
9455                         texture = surface->texture;
9456                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9457                                 continue;
9458                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9459                                 continue;
9460                         numtriangles = surface->num_triangles;
9461                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
9462                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
9463                 }
9464         }
9465 }
9466
9467 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9468 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)
9469 {
9470         int renderentityindex;
9471         float worldmins[3];
9472         float worldmaxs[3];
9473         entity_render_t *ent;
9474
9475         if (!cl_decals_newsystem.integer)
9476                 return;
9477
9478         worldmins[0] = worldorigin[0] - worldsize;
9479         worldmins[1] = worldorigin[1] - worldsize;
9480         worldmins[2] = worldorigin[2] - worldsize;
9481         worldmaxs[0] = worldorigin[0] + worldsize;
9482         worldmaxs[1] = worldorigin[1] + worldsize;
9483         worldmaxs[2] = worldorigin[2] + worldsize;
9484
9485         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9486
9487         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9488         {
9489                 ent = r_refdef.scene.entities[renderentityindex];
9490                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9491                         continue;
9492
9493                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9494         }
9495 }
9496
9497 typedef struct r_decalsystem_splatqueue_s
9498 {
9499         vec3_t worldorigin;
9500         vec3_t worldnormal;
9501         float color[4];
9502         float tcrange[4];
9503         float worldsize;
9504         unsigned int decalsequence;
9505 }
9506 r_decalsystem_splatqueue_t;
9507
9508 int r_decalsystem_numqueued = 0;
9509 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9510
9511 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)
9512 {
9513         r_decalsystem_splatqueue_t *queue;
9514
9515         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9516                 return;
9517
9518         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9519         VectorCopy(worldorigin, queue->worldorigin);
9520         VectorCopy(worldnormal, queue->worldnormal);
9521         Vector4Set(queue->color, r, g, b, a);
9522         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9523         queue->worldsize = worldsize;
9524         queue->decalsequence = cl.decalsequence++;
9525 }
9526
9527 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9528 {
9529         int i;
9530         r_decalsystem_splatqueue_t *queue;
9531
9532         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9533                 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);
9534         r_decalsystem_numqueued = 0;
9535 }
9536
9537 extern cvar_t cl_decals_max;
9538 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9539 {
9540         int i;
9541         decalsystem_t *decalsystem = &ent->decalsystem;
9542         int numdecals;
9543         unsigned int killsequence;
9544         tridecal_t *decal;
9545         float frametime;
9546         float lifetime;
9547
9548         if (!decalsystem->numdecals)
9549                 return;
9550
9551         if (r_showsurfaces.integer)
9552                 return;
9553
9554         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9555         {
9556                 R_DecalSystem_Reset(decalsystem);
9557                 return;
9558         }
9559
9560         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
9561         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9562
9563         if (decalsystem->lastupdatetime)
9564                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
9565         else
9566                 frametime = 0;
9567         decalsystem->lastupdatetime = r_refdef.scene.time;
9568         numdecals = decalsystem->numdecals;
9569
9570         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9571         {
9572                 if (decal->color4f[0][3])
9573                 {
9574                         decal->lived += frametime;
9575                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
9576                         {
9577                                 memset(decal, 0, sizeof(*decal));
9578                                 if (decalsystem->freedecal > i)
9579                                         decalsystem->freedecal = i;
9580                         }
9581                 }
9582         }
9583         decal = decalsystem->decals;
9584         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
9585                 numdecals--;
9586
9587         // collapse the array by shuffling the tail decals into the gaps
9588         for (;;)
9589         {
9590                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
9591                         decalsystem->freedecal++;
9592                 if (decalsystem->freedecal == numdecals)
9593                         break;
9594                 decal[decalsystem->freedecal] = decal[--numdecals];
9595         }
9596
9597         decalsystem->numdecals = numdecals;
9598
9599         if (numdecals <= 0)
9600         {
9601                 // if there are no decals left, reset decalsystem
9602                 R_DecalSystem_Reset(decalsystem);
9603         }
9604 }
9605
9606 extern skinframe_t *decalskinframe;
9607 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9608 {
9609         int i;
9610         decalsystem_t *decalsystem = &ent->decalsystem;
9611         int numdecals;
9612         tridecal_t *decal;
9613         float faderate;
9614         float alpha;
9615         float *v3f;
9616         float *c4f;
9617         float *t2f;
9618         const int *e;
9619         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9620         int numtris = 0;
9621
9622         numdecals = decalsystem->numdecals;
9623         if (!numdecals)
9624                 return;
9625
9626         if (r_showsurfaces.integer)
9627                 return;
9628
9629         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9630         {
9631                 R_DecalSystem_Reset(decalsystem);
9632                 return;
9633         }
9634
9635         // if the model is static it doesn't matter what value we give for
9636         // wantnormals and wanttangents, so this logic uses only rules applicable
9637         // to a model, knowing that they are meaningless otherwise
9638         RSurf_ActiveModelEntity(ent, false, false, false);
9639
9640         decalsystem->lastupdatetime = r_refdef.scene.time;
9641
9642         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9643
9644         // update vertex positions for animated models
9645         v3f = decalsystem->vertex3f;
9646         c4f = decalsystem->color4f;
9647         t2f = decalsystem->texcoord2f;
9648         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9649         {
9650                 if (!decal->color4f[0][3])
9651                         continue;
9652
9653                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9654                         continue;
9655
9656                 // skip backfaces
9657                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
9658                         continue;
9659
9660                 // update color values for fading decals
9661                 if (decal->lived >= cl_decals_time.value)
9662                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9663                 else
9664                         alpha = 1.0f;
9665
9666                 c4f[ 0] = decal->color4f[0][0] * alpha;
9667                 c4f[ 1] = decal->color4f[0][1] * alpha;
9668                 c4f[ 2] = decal->color4f[0][2] * alpha;
9669                 c4f[ 3] = 1;
9670                 c4f[ 4] = decal->color4f[1][0] * alpha;
9671                 c4f[ 5] = decal->color4f[1][1] * alpha;
9672                 c4f[ 6] = decal->color4f[1][2] * alpha;
9673                 c4f[ 7] = 1;
9674                 c4f[ 8] = decal->color4f[2][0] * alpha;
9675                 c4f[ 9] = decal->color4f[2][1] * alpha;
9676                 c4f[10] = decal->color4f[2][2] * alpha;
9677                 c4f[11] = 1;
9678
9679                 t2f[0] = decal->texcoord2f[0][0];
9680                 t2f[1] = decal->texcoord2f[0][1];
9681                 t2f[2] = decal->texcoord2f[1][0];
9682                 t2f[3] = decal->texcoord2f[1][1];
9683                 t2f[4] = decal->texcoord2f[2][0];
9684                 t2f[5] = decal->texcoord2f[2][1];
9685
9686                 // update vertex positions for animated models
9687                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
9688                 {
9689                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9690                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
9691                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
9692                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
9693                 }
9694                 else
9695                 {
9696                         VectorCopy(decal->vertex3f[0], v3f);
9697                         VectorCopy(decal->vertex3f[1], v3f + 3);
9698                         VectorCopy(decal->vertex3f[2], v3f + 6);
9699                 }
9700
9701                 if (r_refdef.fogenabled)
9702                 {
9703                         alpha = RSurf_FogVertex(v3f);
9704                         VectorScale(c4f, alpha, c4f);
9705                         alpha = RSurf_FogVertex(v3f + 3);
9706                         VectorScale(c4f + 4, alpha, c4f + 4);
9707                         alpha = RSurf_FogVertex(v3f + 6);
9708                         VectorScale(c4f + 8, alpha, c4f + 8);
9709                 }
9710
9711                 v3f += 9;
9712                 c4f += 12;
9713                 t2f += 6;
9714                 numtris++;
9715         }
9716
9717         if (numtris > 0)
9718         {
9719                 r_refdef.stats[r_stat_drawndecals] += numtris;
9720
9721                 // now render the decals all at once
9722                 // (this assumes they all use one particle font texture!)
9723                 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);
9724 //              R_Mesh_ResetTextureState();
9725                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
9726                 GL_DepthMask(false);
9727                 GL_DepthRange(0, 1);
9728                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9729                 GL_DepthTest(true);
9730                 GL_CullFace(GL_NONE);
9731                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9732                 R_SetupShader_Generic(decalskinframe->base, false, false, false);
9733                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
9734         }
9735 }
9736
9737 static void R_DrawModelDecals(void)
9738 {
9739         int i, numdecals;
9740
9741         // fade faster when there are too many decals
9742         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9743         for (i = 0;i < r_refdef.scene.numentities;i++)
9744                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9745
9746         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9747         for (i = 0;i < r_refdef.scene.numentities;i++)
9748                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9749                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9750
9751         R_DecalSystem_ApplySplatEntitiesQueue();
9752
9753         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9754         for (i = 0;i < r_refdef.scene.numentities;i++)
9755                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9756
9757         r_refdef.stats[r_stat_totaldecals] += numdecals;
9758
9759         if (r_showsurfaces.integer)
9760                 return;
9761
9762         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9763
9764         for (i = 0;i < r_refdef.scene.numentities;i++)
9765         {
9766                 if (!r_refdef.viewcache.entityvisible[i])
9767                         continue;
9768                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9769                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9770         }
9771 }
9772
9773 extern cvar_t mod_collision_bih;
9774 static void R_DrawDebugModel(void)
9775 {
9776         entity_render_t *ent = rsurface.entity;
9777         int i, j, flagsmask;
9778         const msurface_t *surface;
9779         dp_model_t *model = ent->model;
9780
9781         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
9782                 return;
9783
9784         if (r_showoverdraw.value > 0)
9785         {
9786                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
9787                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9788                 R_SetupShader_Generic_NoTexture(false, false);
9789                 GL_DepthTest(false);
9790                 GL_DepthMask(false);
9791                 GL_DepthRange(0, 1);
9792                 GL_BlendFunc(GL_ONE, GL_ONE);
9793                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9794                 {
9795                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9796                                 continue;
9797                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9798                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9799                         {
9800                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9801                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9802                                 if (!rsurface.texture->currentlayers->depthmask)
9803                                         GL_Color(c, 0, 0, 1.0f);
9804                                 else if (ent == r_refdef.scene.worldentity)
9805                                         GL_Color(c, c, c, 1.0f);
9806                                 else
9807                                         GL_Color(0, c, 0, 1.0f);
9808                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9809                                 RSurf_DrawBatch();
9810                         }
9811                 }
9812                 rsurface.texture = NULL;
9813         }
9814
9815         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9816
9817 //      R_Mesh_ResetTextureState();
9818         R_SetupShader_Generic_NoTexture(false, false);
9819         GL_DepthRange(0, 1);
9820         GL_DepthTest(!r_showdisabledepthtest.integer);
9821         GL_DepthMask(false);
9822         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9823
9824         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
9825         {
9826                 int triangleindex;
9827                 int bihleafindex;
9828                 qboolean cullbox = false;
9829                 const q3mbrush_t *brush;
9830                 const bih_t *bih = &model->collision_bih;
9831                 const bih_leaf_t *bihleaf;
9832                 float vertex3f[3][3];
9833                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9834                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
9835                 {
9836                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
9837                                 continue;
9838                         switch (bihleaf->type)
9839                         {
9840                         case BIH_BRUSH:
9841                                 brush = model->brush.data_brushes + bihleaf->itemindex;
9842                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
9843                                 {
9844                                         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);
9845                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
9846                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
9847                                 }
9848                                 break;
9849                         case BIH_COLLISIONTRIANGLE:
9850                                 triangleindex = bihleaf->itemindex;
9851                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
9852                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
9853                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
9854                                 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);
9855                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9856                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9857                                 break;
9858                         case BIH_RENDERTRIANGLE:
9859                                 triangleindex = bihleaf->itemindex;
9860                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
9861                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
9862                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
9863                                 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);
9864                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9865                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9866                                 break;
9867                         }
9868                 }
9869         }
9870
9871         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9872
9873 #ifndef USE_GLES2
9874         if (r_showtris.value > 0 && qglPolygonMode)
9875         {
9876                 if (r_showdisabledepthtest.integer)
9877                 {
9878                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9879                         GL_DepthMask(false);
9880                 }
9881                 else
9882                 {
9883                         GL_BlendFunc(GL_ONE, GL_ZERO);
9884                         GL_DepthMask(true);
9885                 }
9886                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
9887                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9888                 {
9889                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9890                                 continue;
9891                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9892                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9893                         {
9894                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9895                                 if (!rsurface.texture->currentlayers->depthmask)
9896                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9897                                 else if (ent == r_refdef.scene.worldentity)
9898                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9899                                 else
9900                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9901                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9902                                 RSurf_DrawBatch();
9903                         }
9904                 }
9905                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
9906                 rsurface.texture = NULL;
9907         }
9908
9909 # if 0
9910         // FIXME!  implement r_shownormals with just triangles
9911         if (r_shownormals.value != 0 && qglBegin)
9912         {
9913                 int l, k;
9914                 vec3_t v;
9915                 if (r_showdisabledepthtest.integer)
9916                 {
9917                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9918                         GL_DepthMask(false);
9919                 }
9920                 else
9921                 {
9922                         GL_BlendFunc(GL_ONE, GL_ZERO);
9923                         GL_DepthMask(true);
9924                 }
9925                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9926                 {
9927                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9928                                 continue;
9929                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9930                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9931                         {
9932                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9933                                 qglBegin(GL_LINES);
9934                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
9935                                 {
9936                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9937                                         {
9938                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9939                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9940                                                 qglVertex3f(v[0], v[1], v[2]);
9941                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
9942                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9943                                                 qglVertex3f(v[0], v[1], v[2]);
9944                                         }
9945                                 }
9946                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
9947                                 {
9948                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9949                                         {
9950                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9951                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9952                                                 qglVertex3f(v[0], v[1], v[2]);
9953                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
9954                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9955                                                 qglVertex3f(v[0], v[1], v[2]);
9956                                         }
9957                                 }
9958                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
9959                                 {
9960                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9961                                         {
9962                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9963                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9964                                                 qglVertex3f(v[0], v[1], v[2]);
9965                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
9966                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9967                                                 qglVertex3f(v[0], v[1], v[2]);
9968                                         }
9969                                 }
9970                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
9971                                 {
9972                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9973                                         {
9974                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9975                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9976                                                 qglVertex3f(v[0], v[1], v[2]);
9977                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
9978                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9979                                                 qglVertex3f(v[0], v[1], v[2]);
9980                                         }
9981                                 }
9982                                 qglEnd();
9983                                 CHECKGLERROR
9984                         }
9985                 }
9986                 rsurface.texture = NULL;
9987         }
9988 # endif
9989 #endif
9990 }
9991
9992 int r_maxsurfacelist = 0;
9993 const msurface_t **r_surfacelist = NULL;
9994 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass, qboolean ui)
9995 {
9996         int i, j, endj, flagsmask;
9997         dp_model_t *model = ent->model;
9998         msurface_t *surfaces;
9999         unsigned char *update;
10000         int numsurfacelist = 0;
10001         if (model == NULL)
10002                 return;
10003
10004         if (r_maxsurfacelist < model->num_surfaces)
10005         {
10006                 r_maxsurfacelist = model->num_surfaces;
10007                 if (r_surfacelist)
10008                         Mem_Free((msurface_t **)r_surfacelist);
10009                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10010         }
10011
10012         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10013                 RSurf_ActiveModelEntity(ent, false, false, false);
10014         else if (prepass)
10015                 RSurf_ActiveModelEntity(ent, true, true, true);
10016         else if (depthonly)
10017                 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
10018         else
10019                 RSurf_ActiveModelEntity(ent, true, true, false);
10020
10021         surfaces = model->data_surfaces;
10022         update = model->brushq1.lightmapupdateflags;
10023
10024         // update light styles
10025         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
10026         {
10027                 model_brush_lightstyleinfo_t *style;
10028                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10029                 {
10030                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10031                         {
10032                                 int *list = style->surfacelist;
10033                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10034                                 for (j = 0;j < style->numsurfaces;j++)
10035                                         update[list[j]] = true;
10036                         }
10037                 }
10038         }
10039
10040         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10041
10042         if (debug)
10043         {
10044                 R_DrawDebugModel();
10045                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10046                 return;
10047         }
10048
10049         rsurface.lightmaptexture = NULL;
10050         rsurface.deluxemaptexture = NULL;
10051         rsurface.uselightmaptexture = false;
10052         rsurface.texture = NULL;
10053         rsurface.rtlight = NULL;
10054         numsurfacelist = 0;
10055         // add visible surfaces to draw list
10056         if (ent == r_refdef.scene.worldentity)
10057         {
10058                 // for the world entity, check surfacevisible
10059                 for (i = 0;i < model->nummodelsurfaces;i++)
10060                 {
10061                         j = model->sortedmodelsurfaces[i];
10062                         if (r_refdef.viewcache.world_surfacevisible[j])
10063                                 r_surfacelist[numsurfacelist++] = surfaces + j;
10064                 }
10065         }
10066         else if (ui)
10067         {
10068                 // for ui we have to preserve the order of surfaces
10069                 for (i = 0; i < model->nummodelsurfaces; i++)
10070                         r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i;
10071         }
10072         else
10073         {
10074                 // add all surfaces
10075                 for (i = 0; i < model->nummodelsurfaces; i++)
10076                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10077         }
10078         // don't do anything if there were no surfaces
10079         if (!numsurfacelist)
10080         {
10081                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10082                 return;
10083         }
10084         // update lightmaps if needed
10085         if (update)
10086         {
10087                 int updated = 0;
10088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10089                 {
10090                         if (update[j])
10091                         {
10092                                 updated++;
10093                                 R_BuildLightMap(ent, surfaces + j);
10094                         }
10095                 }
10096         }
10097
10098         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass, ui);
10099
10100         // add to stats if desired
10101         if (r_speeds.integer && !skysurfaces && !depthonly)
10102         {
10103                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
10104                 for (j = 0;j < numsurfacelist;j++)
10105                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
10106         }
10107
10108         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10109 }
10110
10111 void R_DebugLine(vec3_t start, vec3_t end)
10112 {
10113         dp_model_t *mod = CL_Mesh_UI();
10114         msurface_t *surf;
10115         int e0, e1, e2, e3;
10116         float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
10117         float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
10118         float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
10119         vec4_t w[2], s[2];
10120
10121         // transform to screen coords first
10122         Vector4Set(w[0], start[0], start[1], start[2], 1);
10123         Vector4Set(w[1], end[0], end[1], end[2], 1);
10124         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
10125         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
10126         x1 = s[0][0] * vid_conwidth.value / vid.width;
10127         y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
10128         x2 = s[1][0] * vid_conwidth.value / vid.width;
10129         y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
10130         //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
10131
10132         // add the line to the UI mesh for drawing later
10133
10134         // width is measured in real pixels
10135         if (fabs(x2 - x1) > fabs(y2 - y1))
10136         {
10137                 offsetx = 0;
10138                 offsety = 0.5f * width * vid_conheight.value / vid.height;
10139         }
10140         else
10141         {
10142                 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
10143                 offsety = 0;
10144         }
10145         surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX), true);
10146         e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10147         e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10148         e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10149         e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10150         Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
10151         Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
10152
10153 }
10154
10155
10156 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10157 {
10158         int q;
10159         static texture_t texture;
10160         static msurface_t surface;
10161         const msurface_t *surfacelist = &surface;
10162
10163         // fake enough texture and surface state to render this geometry
10164
10165         texture.update_lastrenderframe = -1; // regenerate this texture
10166         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10167         texture.basealpha = 1.0f;
10168         texture.currentskinframe = skinframe;
10169         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10170         texture.offsetmapping = OFFSETMAPPING_OFF;
10171         texture.offsetscale = 1;
10172         texture.specularscalemod = 1;
10173         texture.specularpowermod = 1;
10174         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
10175         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
10176         // JUST GREP FOR "specularscalemod = 1".
10177
10178         for (q = 0; q < 3; q++)
10179         {
10180                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
10181                 texture.render_modellight_lightdir[q] = q == 2;
10182                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10183                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
10184                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
10185                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10186                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
10187                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
10188                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
10189                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
10190         }
10191         texture.currentalpha = 1.0f;
10192
10193         surface.texture = &texture;
10194         surface.num_triangles = numtriangles;
10195         surface.num_firsttriangle = firsttriangle;
10196         surface.num_vertices = numvertices;
10197         surface.num_firstvertex = firstvertex;
10198
10199         // now render it
10200         rsurface.texture = R_GetCurrentTexture(surface.texture);
10201         rsurface.lightmaptexture = NULL;
10202         rsurface.deluxemaptexture = NULL;
10203         rsurface.uselightmaptexture = false;
10204         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10205 }
10206
10207 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)
10208 {
10209         static msurface_t surface;
10210         const msurface_t *surfacelist = &surface;
10211
10212         // fake enough texture and surface state to render this geometry
10213         surface.texture = texture;
10214         surface.num_triangles = numtriangles;
10215         surface.num_firsttriangle = firsttriangle;
10216         surface.num_vertices = numvertices;
10217         surface.num_firstvertex = firstvertex;
10218
10219         // now render it
10220         rsurface.texture = R_GetCurrentTexture(surface.texture);
10221         rsurface.lightmaptexture = NULL;
10222         rsurface.deluxemaptexture = NULL;
10223         rsurface.uselightmaptexture = false;
10224         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10225 }