]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
build: minor adjustments
[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 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 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%)" };
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
96 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
97 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
98 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
99 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
100 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
101 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
102 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
103 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)"};
104 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)"};
105 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
106 cvar_t r_cullentities_trace_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
107 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
108 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
109 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"};
110 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
111 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
112 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
113
114 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"};
115 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
116 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
117 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"};
118 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"};
119
120 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
121 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
122 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
123 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."};
124 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
125 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
126 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
127 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."};
128 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
129 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
130 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."};
131 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."};
132 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
133 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"};
134 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"};
135 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
136 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
137 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
138 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
139 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
140 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"};
141 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
142 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
143 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
144 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
145 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
146
147 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
148 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
149 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
150 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
151 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
152 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
153 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
154 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
155
156 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)"};
157 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"};
158
159 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
160 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
161 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
162
163 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"};
164 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"};
165 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)"};
166 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"};
167 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
168 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
169 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"};
170 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)"};
171 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)"};
172 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
173
174 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
175 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)"};
176 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
177 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)"};
178 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
179 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)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
182 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"};
183 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."};
184 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
185 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)"};
186 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)"};
187 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)"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193
194 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)"};
195 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)"};
196 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
197 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"};
198 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
199 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
200 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
201 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"};
202 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"};
203
204 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
205 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
206 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
207 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
208
209 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
210 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
211
212 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
213 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
214 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
215 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
216 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
217 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
218
219 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
220 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
221 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
222 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
223 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
224 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
225 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
226 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
227 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
228 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
229
230 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"};
231
232 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"};
233
234 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
235
236 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
237
238 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)"};
239 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)"};
240 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
241 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
242
243 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
244 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"};
245
246 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."};
247
248 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)"};
249 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
250 {
251         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
252         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
253         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
254         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
255 };
256
257 extern cvar_t v_glslgamma_2d;
258
259 extern qboolean v_flipped_state;
260
261 r_framebufferstate_t r_fb;
262
263 /// shadow volume bsp struct with automatically growing nodes buffer
264 svbsp_t r_svbsp;
265
266 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
267
268 rtexture_t *r_texture_blanknormalmap;
269 rtexture_t *r_texture_white;
270 rtexture_t *r_texture_grey128;
271 rtexture_t *r_texture_black;
272 rtexture_t *r_texture_notexture;
273 rtexture_t *r_texture_whitecube;
274 rtexture_t *r_texture_normalizationcube;
275 rtexture_t *r_texture_fogattenuation;
276 rtexture_t *r_texture_fogheighttexture;
277 rtexture_t *r_texture_gammaramps;
278 unsigned int r_texture_gammaramps_serial;
279 //rtexture_t *r_texture_fogintensity;
280 rtexture_t *r_texture_reflectcube;
281
282 // TODO: hash lookups?
283 typedef struct cubemapinfo_s
284 {
285         char basename[64];
286         rtexture_t *texture;
287 }
288 cubemapinfo_t;
289
290 int r_texture_numcubemaps;
291 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
292
293 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
294 unsigned int r_numqueries;
295 unsigned int r_maxqueries;
296
297 typedef struct r_qwskincache_s
298 {
299         char name[MAX_QPATH];
300         skinframe_t *skinframe;
301 }
302 r_qwskincache_t;
303
304 static r_qwskincache_t *r_qwskincache;
305 static int r_qwskincache_size;
306
307 /// vertex coordinates for a quad that covers the screen exactly
308 extern const float r_screenvertex3f[12];
309 const float r_screenvertex3f[12] =
310 {
311         0, 0, 0,
312         1, 0, 0,
313         1, 1, 0,
314         0, 1, 0
315 };
316
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
318 {
319         int i;
320         for (i = 0;i < verts;i++)
321         {
322                 out[0] = in[0] * r;
323                 out[1] = in[1] * g;
324                 out[2] = in[2] * b;
325                 out[3] = in[3];
326                 in += 4;
327                 out += 4;
328         }
329 }
330
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
332 {
333         int i;
334         for (i = 0;i < verts;i++)
335         {
336                 out[0] = r;
337                 out[1] = g;
338                 out[2] = b;
339                 out[3] = a;
340                 out += 4;
341         }
342 }
343
344 // FIXME: move this to client?
345 void FOG_clear(void)
346 {
347         if (gamemode == GAME_NEHAHRA)
348         {
349                 Cvar_Set("gl_fogenable", "0");
350                 Cvar_Set("gl_fogdensity", "0.2");
351                 Cvar_Set("gl_fogred", "0.3");
352                 Cvar_Set("gl_foggreen", "0.3");
353                 Cvar_Set("gl_fogblue", "0.3");
354         }
355         r_refdef.fog_density = 0;
356         r_refdef.fog_red = 0;
357         r_refdef.fog_green = 0;
358         r_refdef.fog_blue = 0;
359         r_refdef.fog_alpha = 1;
360         r_refdef.fog_start = 0;
361         r_refdef.fog_end = 16384;
362         r_refdef.fog_height = 1<<30;
363         r_refdef.fog_fadedepth = 128;
364         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
365 }
366
367 static void R_BuildBlankTextures(void)
368 {
369         unsigned char data[4];
370         data[2] = 128; // normal X
371         data[1] = 128; // normal Y
372         data[0] = 255; // normal Z
373         data[3] = 255; // height
374         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 255;
376         data[1] = 255;
377         data[2] = 255;
378         data[3] = 255;
379         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 128;
381         data[1] = 128;
382         data[2] = 128;
383         data[3] = 255;
384         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 0;
386         data[1] = 0;
387         data[2] = 0;
388         data[3] = 255;
389         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 }
391
392 static void R_BuildNoTexture(void)
393 {
394         int x, y;
395         unsigned char pix[16][16][4];
396         // this makes a light grey/dark grey checkerboard texture
397         for (y = 0;y < 16;y++)
398         {
399                 for (x = 0;x < 16;x++)
400                 {
401                         if ((y < 8) ^ (x < 8))
402                         {
403                                 pix[y][x][0] = 128;
404                                 pix[y][x][1] = 128;
405                                 pix[y][x][2] = 128;
406                                 pix[y][x][3] = 255;
407                         }
408                         else
409                         {
410                                 pix[y][x][0] = 64;
411                                 pix[y][x][1] = 64;
412                                 pix[y][x][2] = 64;
413                                 pix[y][x][3] = 255;
414                         }
415                 }
416         }
417         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
418 }
419
420 static void R_BuildWhiteCube(void)
421 {
422         unsigned char data[6*1*1*4];
423         memset(data, 255, sizeof(data));
424         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildNormalizationCube(void)
428 {
429         int x, y, side;
430         vec3_t v;
431         vec_t s, t, intensity;
432 #define NORMSIZE 64
433         unsigned char *data;
434         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435         for (side = 0;side < 6;side++)
436         {
437                 for (y = 0;y < NORMSIZE;y++)
438                 {
439                         for (x = 0;x < NORMSIZE;x++)
440                         {
441                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 switch(side)
444                                 {
445                                 default:
446                                 case 0:
447                                         v[0] = 1;
448                                         v[1] = -t;
449                                         v[2] = -s;
450                                         break;
451                                 case 1:
452                                         v[0] = -1;
453                                         v[1] = -t;
454                                         v[2] = s;
455                                         break;
456                                 case 2:
457                                         v[0] = s;
458                                         v[1] = 1;
459                                         v[2] = t;
460                                         break;
461                                 case 3:
462                                         v[0] = s;
463                                         v[1] = -1;
464                                         v[2] = -t;
465                                         break;
466                                 case 4:
467                                         v[0] = s;
468                                         v[1] = -t;
469                                         v[2] = 1;
470                                         break;
471                                 case 5:
472                                         v[0] = -s;
473                                         v[1] = -t;
474                                         v[2] = -1;
475                                         break;
476                                 }
477                                 intensity = 127.0f / sqrt(DotProduct(v, v));
478                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481                                 data[((side*64+y)*64+x)*4+3] = 255;
482                         }
483                 }
484         }
485         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
486         Mem_Free(data);
487 }
488
489 static void R_BuildFogTexture(void)
490 {
491         int x, b;
492 #define FOGWIDTH 256
493         unsigned char data1[FOGWIDTH][4];
494         //unsigned char data2[FOGWIDTH][4];
495         double d, r, alpha;
496
497         r_refdef.fogmasktable_start = r_refdef.fog_start;
498         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499         r_refdef.fogmasktable_range = r_refdef.fogrange;
500         r_refdef.fogmasktable_density = r_refdef.fog_density;
501
502         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
504         {
505                 d = (x * r - r_refdef.fogmasktable_start);
506                 if(developer_extra.integer)
507                         Con_DPrintf("%f ", d);
508                 d = max(0, d);
509                 if (r_fog_exp2.integer)
510                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
511                 else
512                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513                 if(developer_extra.integer)
514                         Con_DPrintf(" : %f ", alpha);
515                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516                 if(developer_extra.integer)
517                         Con_DPrintf(" = %f\n", alpha);
518                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
519         }
520
521         for (x = 0;x < FOGWIDTH;x++)
522         {
523                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
524                 data1[x][0] = b;
525                 data1[x][1] = b;
526                 data1[x][2] = b;
527                 data1[x][3] = 255;
528                 //data2[x][0] = 255 - b;
529                 //data2[x][1] = 255 - b;
530                 //data2[x][2] = 255 - b;
531                 //data2[x][3] = 255;
532         }
533         if (r_texture_fogattenuation)
534         {
535                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537         }
538         else
539         {
540                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
542         }
543 }
544
545 static void R_BuildFogHeightTexture(void)
546 {
547         unsigned char *inpixels;
548         int size;
549         int x;
550         int y;
551         int j;
552         float c[4];
553         float f;
554         inpixels = NULL;
555         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556         if (r_refdef.fogheighttexturename[0])
557                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
558         if (!inpixels)
559         {
560                 r_refdef.fog_height_tablesize = 0;
561                 if (r_texture_fogheighttexture)
562                         R_FreeTexture(r_texture_fogheighttexture);
563                 r_texture_fogheighttexture = NULL;
564                 if (r_refdef.fog_height_table2d)
565                         Mem_Free(r_refdef.fog_height_table2d);
566                 r_refdef.fog_height_table2d = NULL;
567                 if (r_refdef.fog_height_table1d)
568                         Mem_Free(r_refdef.fog_height_table1d);
569                 r_refdef.fog_height_table1d = NULL;
570                 return;
571         }
572         size = image_width;
573         r_refdef.fog_height_tablesize = size;
574         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
577         Mem_Free(inpixels);
578         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
579         // average fog color table accounting for every fog layer between a point
580         // and the camera.  (Note: attenuation is handled separately!)
581         for (y = 0;y < size;y++)
582         {
583                 for (x = 0;x < size;x++)
584                 {
585                         Vector4Clear(c);
586                         f = 0;
587                         if (x < y)
588                         {
589                                 for (j = x;j <= y;j++)
590                                 {
591                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592                                         f++;
593                                 }
594                         }
595                         else
596                         {
597                                 for (j = x;j >= y;j--)
598                                 {
599                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600                                         f++;
601                                 }
602                         }
603                         f = 1.0f / f;
604                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
608                 }
609         }
610         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
611 }
612
613 //=======================================================================================================================================================
614
615 static const char *builtinshaderstrings[] =
616 {
617 #include "shader_glsl.h"
618 0
619 };
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *sourcebasename;
633         const char *extension;
634         const char **builtinshaderstrings;
635         const char *pretext;
636         const char *name;
637         char *filename;
638         char *builtinstring;
639         int builtincrc;
640 }
641 shadermodeinfo_t;
642
643 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
644 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
645 {
646         {"#define USEDIFFUSE\n", " diffuse"},
647         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
648         {"#define USEVIEWTINT\n", " viewtint"},
649         {"#define USECOLORMAPPING\n", " colormapping"},
650         {"#define USESATURATION\n", " saturation"},
651         {"#define USEFOGINSIDE\n", " foginside"},
652         {"#define USEFOGOUTSIDE\n", " fogoutside"},
653         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
654         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
655         {"#define USEGAMMARAMPS\n", " gammaramps"},
656         {"#define USECUBEFILTER\n", " cubefilter"},
657         {"#define USEGLOW\n", " glow"},
658         {"#define USEBLOOM\n", " bloom"},
659         {"#define USESPECULAR\n", " specular"},
660         {"#define USEPOSTPROCESSING\n", " postprocessing"},
661         {"#define USEREFLECTION\n", " reflection"},
662         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
663         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
664         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
673         {"#define USETRIPPY\n", " trippy"},
674         {"#define USEDEPTHRGB\n", " depthrgb"},
675         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
676         {"#define USESKELETAL\n", " skeletal"},
677         {"#define USEOCCLUDE\n", " occlude"}
678 };
679
680 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
681 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
682 {
683         // SHADERLANGUAGE_GLSL
684         {
685                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
686                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
687                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
689                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
691                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
697                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
698                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
699                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701         },
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         dpuint64 permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenNormalMap;
741         int tex_Texture_ScreenDiffuse;
742         int tex_Texture_ScreenSpecular;
743         int tex_Texture_ReflectMask;
744         int tex_Texture_ReflectCube;
745         int tex_Texture_BounceGrid;
746         /// locations of detected uniforms in program object, or -1 if not found
747         int loc_Texture_First;
748         int loc_Texture_Second;
749         int loc_Texture_GammaRamps;
750         int loc_Texture_Normal;
751         int loc_Texture_Color;
752         int loc_Texture_Gloss;
753         int loc_Texture_Glow;
754         int loc_Texture_SecondaryNormal;
755         int loc_Texture_SecondaryColor;
756         int loc_Texture_SecondaryGloss;
757         int loc_Texture_SecondaryGlow;
758         int loc_Texture_Pants;
759         int loc_Texture_Shirt;
760         int loc_Texture_FogHeightTexture;
761         int loc_Texture_FogMask;
762         int loc_Texture_Lightmap;
763         int loc_Texture_Deluxemap;
764         int loc_Texture_Attenuation;
765         int loc_Texture_Cube;
766         int loc_Texture_Refraction;
767         int loc_Texture_Reflection;
768         int loc_Texture_ShadowMap2D;
769         int loc_Texture_CubeProjection;
770         int loc_Texture_ScreenNormalMap;
771         int loc_Texture_ScreenDiffuse;
772         int loc_Texture_ScreenSpecular;
773         int loc_Texture_ReflectMask;
774         int loc_Texture_ReflectCube;
775         int loc_Texture_BounceGrid;
776         int loc_Alpha;
777         int loc_BloomBlur_Parameters;
778         int loc_ClientTime;
779         int loc_Color_Ambient;
780         int loc_Color_Diffuse;
781         int loc_Color_Specular;
782         int loc_Color_Glow;
783         int loc_Color_Pants;
784         int loc_Color_Shirt;
785         int loc_DeferredColor_Ambient;
786         int loc_DeferredColor_Diffuse;
787         int loc_DeferredColor_Specular;
788         int loc_DeferredMod_Diffuse;
789         int loc_DeferredMod_Specular;
790         int loc_DistortScaleRefractReflect;
791         int loc_EyePosition;
792         int loc_FogColor;
793         int loc_FogHeightFade;
794         int loc_FogPlane;
795         int loc_FogPlaneViewDist;
796         int loc_FogRangeRecip;
797         int loc_LightColor;
798         int loc_LightDir;
799         int loc_LightPosition;
800         int loc_OffsetMapping_ScaleSteps;
801         int loc_OffsetMapping_LodDistance;
802         int loc_OffsetMapping_Bias;
803         int loc_PixelSize;
804         int loc_ReflectColor;
805         int loc_ReflectFactor;
806         int loc_ReflectOffset;
807         int loc_RefractColor;
808         int loc_Saturation;
809         int loc_ScreenCenterRefractReflect;
810         int loc_ScreenScaleRefractReflect;
811         int loc_ScreenToDepth;
812         int loc_ShadowMap_Parameters;
813         int loc_ShadowMap_TextureScale;
814         int loc_SpecularPower;
815         int loc_Skeletal_Transform12;
816         int loc_UserVec1;
817         int loc_UserVec2;
818         int loc_UserVec3;
819         int loc_UserVec4;
820         int loc_ViewTintColor;
821         int loc_ViewToLight;
822         int loc_ModelToLight;
823         int loc_TexMatrix;
824         int loc_BackgroundTexMatrix;
825         int loc_ModelViewProjectionMatrix;
826         int loc_ModelViewMatrix;
827         int loc_PixelToScreenTexCoord;
828         int loc_ModelToReflectCube;
829         int loc_ShadowMapMatrix;
830         int loc_BloomColorSubtract;
831         int loc_NormalmapScrollBlend;
832         int loc_BounceGridMatrix;
833         int loc_BounceGridIntensity;
834         /// uniform block bindings
835         int ubibind_Skeletal_Transform12_UniformBlock;
836         /// uniform block indices
837         int ubiloc_Skeletal_Transform12_UniformBlock;
838 }
839 r_glsl_permutation_t;
840
841 #define SHADERPERMUTATION_HASHSIZE 256
842
843
844 // non-degradable "lightweight" shader parameters to keep the permutations simpler
845 // these can NOT degrade! only use for simple stuff
846 enum
847 {
848         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
849         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
850         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
853         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
854         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
855         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
856         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
857         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
858         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
859         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
860         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
861         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
862 };
863 #define SHADERSTATICPARMS_COUNT 14
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870
871 extern qboolean r_shadow_shadowmapsampler;
872 extern int r_shadow_shadowmappcf;
873 qboolean R_CompileShader_CheckStaticParms(void)
874 {
875         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
876         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
877         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
878
879         // detect all
880         if (r_glsl_saturation_redcompensate.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
882         if (r_glsl_vertextextureblend_usebothalphas.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
884         if (r_shadow_glossexact.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
886         if (r_glsl_postprocess.integer)
887         {
888                 if (r_glsl_postprocess_uservec1_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
890                 if (r_glsl_postprocess_uservec2_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
892                 if (r_glsl_postprocess_uservec3_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
894                 if (r_glsl_postprocess_uservec4_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
896         }
897         if (r_fxaa.integer)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
899         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
900                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
901
902         if (r_shadow_shadowmapsampler)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
904         if (r_shadow_shadowmappcf > 1)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
906         else if (r_shadow_shadowmappcf)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
908         if (r_celshading.integer)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
910         if (r_celoutlines.integer)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
912
913         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
914 }
915
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
919         else \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
922 {
923         shaderstaticparms_count = 0;
924
925         // emit all
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
940 }
941
942 /// information about each possible shader permutation
943 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
944 /// currently selected permutation
945 r_glsl_permutation_t *r_glsl_permutation;
946 /// storage for permutations linked in the hash table
947 memexpandablearray_t r_glsl_permutationarray;
948
949 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
950 {
951         //unsigned int hashdepth = 0;
952         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
953         r_glsl_permutation_t *p;
954         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
955         {
956                 if (p->mode == mode && p->permutation == permutation)
957                 {
958                         //if (hashdepth > 10)
959                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
960                         return p;
961                 }
962                 //hashdepth++;
963         }
964         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
965         p->mode = mode;
966         p->permutation = permutation;
967         p->hashnext = r_glsl_permutationhash[mode][hashindex];
968         r_glsl_permutationhash[mode][hashindex] = p;
969         //if (hashdepth > 10)
970         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
971         return p;
972 }
973
974 static char *R_ShaderStrCat(const char **strings)
975 {
976         char *string, *s;
977         const char **p = strings;
978         const char *t;
979         size_t len = 0;
980         for (p = strings;(t = *p);p++)
981                 len += strlen(t);
982         len++;
983         s = string = (char *)Mem_Alloc(r_main_mempool, len);
984         len = 0;
985         for (p = strings;(t = *p);p++)
986         {
987                 len = strlen(t);
988                 memcpy(s, t, len);
989                 s += len;
990         }
991         *s = 0;
992         return string;
993 }
994
995 static char *R_ShaderStrCat(const char **strings);
996 static void R_InitShaderModeInfo(void)
997 {
998         int i, language;
999         shadermodeinfo_t *modeinfo;
1000         // 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)
1001         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1002         {
1003                 for (i = 0; i < SHADERMODE_COUNT; i++)
1004                 {
1005                         char filename[MAX_QPATH];
1006                         modeinfo = &shadermodeinfo[language][i];
1007                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1008                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1009                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1010                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1011                 }
1012         }
1013 }
1014
1015 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1016 {
1017         char *shaderstring;
1018         // if the mode has no filename we have to return the builtin string
1019         if (builtinonly || !modeinfo->filename)
1020                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1021         // note that FS_LoadFile appends a 0 byte to make it a valid string
1022         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1023         if (shaderstring)
1024         {
1025                 if (printfromdisknotice)
1026                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1027                 return shaderstring;
1028         }
1029         // fall back to builtinstring
1030         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1031 }
1032
1033 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1034 {
1035         int i;
1036         int ubibind;
1037         int sampler;
1038         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1039         char *sourcestring;
1040         char permutationname[256];
1041         int vertstrings_count = 0;
1042         int geomstrings_count = 0;
1043         int fragstrings_count = 0;
1044         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1045         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1046         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1047
1048         if (p->compiled)
1049                 return;
1050         p->compiled = true;
1051         p->program = 0;
1052
1053         permutationname[0] = 0;
1054         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1055
1056         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1057
1058         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1059         if(vid.support.glshaderversion >= 140)
1060         {
1061                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1062                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1063                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1064                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1065                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1066                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1067         }
1068         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1069         else if(vid.support.glshaderversion >= 130)
1070         {
1071                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1072                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1073                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1074                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1075                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1076                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1077         }
1078         // if we can do #version 120, we should (this adds the invariant keyword)
1079         else if(vid.support.glshaderversion >= 120)
1080         {
1081                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1082                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1083                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1084                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1085                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1086                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1087         }
1088         // GLES also adds several things from GLSL120
1089         switch(vid.renderpath)
1090         {
1091         case RENDERPATH_GLES2:
1092                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1093                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1094                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1095                 break;
1096         default:
1097                 break;
1098         }
1099
1100         // the first pretext is which type of shader to compile as
1101         // (later these will all be bound together as a program object)
1102         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1103         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1104         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1105
1106         // the second pretext is the mode (for example a light source)
1107         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1108         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1109         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1110         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1111
1112         // now add all the permutation pretexts
1113         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1114         {
1115                 if (permutation & (1ll<<i))
1116                 {
1117                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1118                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1119                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1120                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1121                 }
1122                 else
1123                 {
1124                         // keep line numbers correct
1125                         vertstrings_list[vertstrings_count++] = "\n";
1126                         geomstrings_list[geomstrings_count++] = "\n";
1127                         fragstrings_list[fragstrings_count++] = "\n";
1128                 }
1129         }
1130
1131         // add static parms
1132         R_CompileShader_AddStaticParms(mode, permutation);
1133         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1134         vertstrings_count += shaderstaticparms_count;
1135         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1136         geomstrings_count += shaderstaticparms_count;
1137         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1138         fragstrings_count += shaderstaticparms_count;
1139
1140         // now append the shader text itself
1141         vertstrings_list[vertstrings_count++] = sourcestring;
1142         geomstrings_list[geomstrings_count++] = sourcestring;
1143         fragstrings_list[fragstrings_count++] = sourcestring;
1144
1145         // we don't currently use geometry shaders for anything, so just empty the list
1146         geomstrings_count = 0;
1147
1148         // compile the shader program
1149         if (vertstrings_count + geomstrings_count + fragstrings_count)
1150                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1151         if (p->program)
1152         {
1153                 CHECKGLERROR
1154                 qglUseProgram(p->program);CHECKGLERROR
1155                 // look up all the uniform variable names we care about, so we don't
1156                 // have to look them up every time we set them
1157
1158 #if 0
1159                 // debugging aid
1160                 {
1161                         GLint activeuniformindex = 0;
1162                         GLint numactiveuniforms = 0;
1163                         char uniformname[128];
1164                         GLsizei uniformnamelength = 0;
1165                         GLint uniformsize = 0;
1166                         GLenum uniformtype = 0;
1167                         memset(uniformname, 0, sizeof(uniformname));
1168                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1169                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1170                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1171                         {
1172                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1173                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1174                         }
1175                 }
1176 #endif
1177
1178                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1179                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1180                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1181                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1182                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1183                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1184                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1185                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1186                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1187                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1188                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1189                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1190                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1191                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1192                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1193                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1194                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1195                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1196                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1197                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1198                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1199                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1200                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1201                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1202                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1203                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1204                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1205                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1206                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1207                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1208                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1209                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1210                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1211                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1212                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1213                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1214                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1215                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1216                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1217                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1218                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1219                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1220                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1221                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1222                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1223                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1224                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1225                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1226                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1227                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1228                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1229                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1230                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1231                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1232                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1233                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1234                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1235                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1236                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1237                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1238                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1239                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1240                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1241                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1242                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1243                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1244                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1245                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1246                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1247                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1248                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1249                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1250                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1251                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1252                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1253                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1254                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1255                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1256                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1257                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1258                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1259                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1260                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1261                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1262                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1263                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1264                 // initialize the samplers to refer to the texture units we use
1265                 p->tex_Texture_First = -1;
1266                 p->tex_Texture_Second = -1;
1267                 p->tex_Texture_GammaRamps = -1;
1268                 p->tex_Texture_Normal = -1;
1269                 p->tex_Texture_Color = -1;
1270                 p->tex_Texture_Gloss = -1;
1271                 p->tex_Texture_Glow = -1;
1272                 p->tex_Texture_SecondaryNormal = -1;
1273                 p->tex_Texture_SecondaryColor = -1;
1274                 p->tex_Texture_SecondaryGloss = -1;
1275                 p->tex_Texture_SecondaryGlow = -1;
1276                 p->tex_Texture_Pants = -1;
1277                 p->tex_Texture_Shirt = -1;
1278                 p->tex_Texture_FogHeightTexture = -1;
1279                 p->tex_Texture_FogMask = -1;
1280                 p->tex_Texture_Lightmap = -1;
1281                 p->tex_Texture_Deluxemap = -1;
1282                 p->tex_Texture_Attenuation = -1;
1283                 p->tex_Texture_Cube = -1;
1284                 p->tex_Texture_Refraction = -1;
1285                 p->tex_Texture_Reflection = -1;
1286                 p->tex_Texture_ShadowMap2D = -1;
1287                 p->tex_Texture_CubeProjection = -1;
1288                 p->tex_Texture_ScreenNormalMap = -1;
1289                 p->tex_Texture_ScreenDiffuse = -1;
1290                 p->tex_Texture_ScreenSpecular = -1;
1291                 p->tex_Texture_ReflectMask = -1;
1292                 p->tex_Texture_ReflectCube = -1;
1293                 p->tex_Texture_BounceGrid = -1;
1294                 // bind the texture samplers in use
1295                 sampler = 0;
1296                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1297                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1298                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1299                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1300                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1301                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1302                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1303                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1304                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1305                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1306                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1307                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1308                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1309                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1310                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1311                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1312                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1313                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1314                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1315                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1316                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1317                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1318                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1319                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1320                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1321                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1322                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1323                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1324                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1325                 // get the uniform block indices so we can bind them
1326                 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1327 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1328                 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1329 #endif
1330                 // clear the uniform block bindings
1331                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1332                 // bind the uniform blocks in use
1333                 ubibind = 0;
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1336 #endif
1337                 // we're done compiling and setting up the shader, at least until it is used
1338                 CHECKGLERROR
1339                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1340         }
1341         else
1342                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1343
1344         // free the strings
1345         if (sourcestring)
1346                 Mem_Free(sourcestring);
1347 }
1348
1349 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1350 {
1351         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1352         if (r_glsl_permutation != perm)
1353         {
1354                 r_glsl_permutation = perm;
1355                 if (!r_glsl_permutation->program)
1356                 {
1357                         if (!r_glsl_permutation->compiled)
1358                         {
1359                                 Con_DPrintf("Compiling shader mode %u permutation %llx\n", mode, permutation);
1360                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1361                         }
1362                         if (!r_glsl_permutation->program)
1363                         {
1364                                 // remove features until we find a valid permutation
1365                                 int i;
1366                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1367                                 {
1368                                         // reduce i more quickly whenever it would not remove any bits
1369                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1370                                         if (!(permutation & j))
1371                                                 continue;
1372                                         permutation -= j;
1373                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1374                                         if (!r_glsl_permutation->compiled)
1375                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1376                                         if (r_glsl_permutation->program)
1377                                                 break;
1378                                 }
1379                                 if (i >= SHADERPERMUTATION_COUNT)
1380                                 {
1381                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1382                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1383                                         qglUseProgram(0);CHECKGLERROR
1384                                         return; // no bit left to clear, entire mode is broken
1385                                 }
1386                         }
1387                 }
1388                 CHECKGLERROR
1389                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1390         }
1391         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1392         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1393         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1394         CHECKGLERROR
1395 }
1396
1397 void R_GLSL_Restart_f(void)
1398 {
1399         unsigned int i, limit;
1400         switch(vid.renderpath)
1401         {
1402         case RENDERPATH_GL32:
1403         case RENDERPATH_GLES2:
1404                 {
1405                         r_glsl_permutation_t *p;
1406                         r_glsl_permutation = NULL;
1407                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1408                         for (i = 0;i < limit;i++)
1409                         {
1410                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1411                                 {
1412                                         GL_Backend_FreeProgram(p->program);
1413                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1414                                 }
1415                         }
1416                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1417                 }
1418                 break;
1419         }
1420 }
1421
1422 static void R_GLSL_DumpShader_f(void)
1423 {
1424         int i, language, mode, dupe;
1425         char *text;
1426         shadermodeinfo_t *modeinfo;
1427         qfile_t *file;
1428
1429         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1430         {
1431                 modeinfo = shadermodeinfo[language];
1432                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1433                 {
1434                         // don't dump the same file multiple times (most or all shaders come from the same file)
1435                         for (dupe = mode - 1;dupe >= 0;dupe--)
1436                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1437                                         break;
1438                         if (dupe >= 0)
1439                                 continue;
1440                         text = modeinfo[mode].builtinstring;
1441                         if (!text)
1442                                 continue;
1443                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1444                         if (file)
1445                         {
1446                                 FS_Print(file, "/* The engine may define the following macros:\n");
1447                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1448                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1449                                         FS_Print(file, modeinfo[i].pretext);
1450                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1451                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1452                                 FS_Print(file, "*/\n");
1453                                 FS_Print(file, text);
1454                                 FS_Close(file);
1455                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1456                         }
1457                         else
1458                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1459                 }
1460         }
1461 }
1462
1463 void R_SetupShader_Generic(rtexture_t *t, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1464 {
1465         dpuint64 permutation = 0;
1466         if (r_trippy.integer && !notrippy)
1467                 permutation |= SHADERPERMUTATION_TRIPPY;
1468         permutation |= SHADERPERMUTATION_VIEWTINT;
1469         if (t)
1470                 permutation |= SHADERPERMUTATION_DIFFUSE;
1471         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1472                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1473         if (suppresstexalpha)
1474                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1475         if (vid.allowalphatocoverage)
1476                 GL_AlphaToCoverage(false);
1477         switch (vid.renderpath)
1478         {
1479         case RENDERPATH_GL32:
1480         case RENDERPATH_GLES2:
1481                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1482                 if (r_glsl_permutation->tex_Texture_First >= 0)
1483                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First, t);
1484                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1485                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1486                 break;
1487         }
1488 }
1489
1490 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1491 {
1492         R_SetupShader_Generic(NULL, usegamma, notrippy, false);
1493 }
1494
1495 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1496 {
1497         dpuint64 permutation = 0;
1498         if (r_trippy.integer && !notrippy)
1499                 permutation |= SHADERPERMUTATION_TRIPPY;
1500         if (depthrgb)
1501                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1502         if (skeletal)
1503                 permutation |= SHADERPERMUTATION_SKELETAL;
1504
1505         if (vid.allowalphatocoverage)
1506                 GL_AlphaToCoverage(false);
1507         switch (vid.renderpath)
1508         {
1509         case RENDERPATH_GL32:
1510         case RENDERPATH_GLES2:
1511                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1512 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1513                 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);
1514 #endif
1515                 break;
1516         }
1517 }
1518
1519 #define BLENDFUNC_ALLOWS_COLORMOD      1
1520 #define BLENDFUNC_ALLOWS_FOG           2
1521 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
1522 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1523 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1524 static int R_BlendFuncFlags(int src, int dst)
1525 {
1526         int r = 0;
1527
1528         // a blendfunc allows colormod if:
1529         // a) it can never keep the destination pixel invariant, or
1530         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1531         // this is to prevent unintended side effects from colormod
1532
1533         // a blendfunc allows fog if:
1534         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
1535         // this is to prevent unintended side effects from fog
1536
1537         // these checks are the output of fogeval.pl
1538
1539         r |= BLENDFUNC_ALLOWS_COLORMOD;
1540         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1541         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1542         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1543         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1544         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1545         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1546         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1547         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1548         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
1549         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
1550         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1551         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1552         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
1553         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1554         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1555         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1556         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1557         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
1558         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
1559         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
1560         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
1561
1562         return r;
1563 }
1564
1565 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)
1566 {
1567         // select a permutation of the lighting shader appropriate to this
1568         // combination of texture, entity, light source, and fogging, only use the
1569         // minimum features necessary to avoid wasting rendering time in the
1570         // fragment shader on features that are not being used
1571         dpuint64 permutation = 0;
1572         unsigned int mode = 0;
1573         int blendfuncflags;
1574         texture_t *t = rsurface.texture;
1575         float m16f[16];
1576         matrix4x4_t tempmatrix;
1577         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
1578         if (r_trippy.integer && !notrippy)
1579                 permutation |= SHADERPERMUTATION_TRIPPY;
1580         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
1581                 permutation |= SHADERPERMUTATION_ALPHAKILL;
1582         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
1583                 permutation |= SHADERPERMUTATION_OCCLUDE;
1584         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
1585                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
1586         if (rsurfacepass == RSURFPASS_BACKGROUND)
1587         {
1588                 // distorted background
1589                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1590                 {
1591                         mode = SHADERMODE_WATER;
1592                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1593                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1594                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
1595                         {
1596                                 // this is the right thing to do for wateralpha
1597                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1598                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1599                         }
1600                         else
1601                         {
1602                                 // this is the right thing to do for entity alpha
1603                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1604                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1605                         }
1606                 }
1607                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
1608                 {
1609                         mode = SHADERMODE_REFRACTION;
1610                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1611                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1612                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1613                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1614                 }
1615                 else
1616                 {
1617                         mode = SHADERMODE_GENERIC;
1618                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
1619                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1620                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1621                 }
1622                 if (vid.allowalphatocoverage)
1623                         GL_AlphaToCoverage(false);
1624         }
1625         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
1626         {
1627                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1628                 {
1629                         switch(t->offsetmapping)
1630                         {
1631                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1632                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1633                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1634                         case OFFSETMAPPING_OFF: break;
1635                         }
1636                 }
1637                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1638                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1639                 // normalmap (deferred prepass), may use alpha test on diffuse
1640                 mode = SHADERMODE_DEFERREDGEOMETRY;
1641                 GL_BlendFunc(GL_ONE, GL_ZERO);
1642                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
1643                 if (vid.allowalphatocoverage)
1644                         GL_AlphaToCoverage(false);
1645         }
1646         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1647         {
1648                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1649                 {
1650                         switch(t->offsetmapping)
1651                         {
1652                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1653                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1654                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1655                         case OFFSETMAPPING_OFF: break;
1656                         }
1657                 }
1658                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1659                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1660                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1661                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1662                 // light source
1663                 mode = SHADERMODE_LIGHTSOURCE;
1664                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1665                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1666                 if (VectorLength2(rtlightdiffuse) > 0)
1667                         permutation |= SHADERPERMUTATION_DIFFUSE;
1668                 if (VectorLength2(rtlightspecular) > 0)
1669                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1670                 if (r_refdef.fogenabled)
1671                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1672                 if (t->colormapping)
1673                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1674                 if (r_shadow_usingshadowmap2d)
1675                 {
1676                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1677                         if(r_shadow_shadowmapvsdct)
1678                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
1679
1680                         if (r_shadow_shadowmap2ddepthbuffer)
1681                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1682                 }
1683                 if (t->reflectmasktexture)
1684                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1685                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1686                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
1687                 if (vid.allowalphatocoverage)
1688                         GL_AlphaToCoverage(false);
1689         }
1690         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1691         {
1692                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1693                 {
1694                         switch(t->offsetmapping)
1695                         {
1696                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1697                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1698                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1699                         case OFFSETMAPPING_OFF: break;
1700                         }
1701                 }
1702                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1703                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1704                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1705                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1706                 // directional model lighting
1707                 mode = SHADERMODE_LIGHTDIRECTION;
1708                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1709                         permutation |= SHADERPERMUTATION_GLOW;
1710                 if (VectorLength2(t->render_modellight_diffuse))
1711                         permutation |= SHADERPERMUTATION_DIFFUSE;
1712                 if (VectorLength2(t->render_modellight_specular) > 0)
1713                         permutation |= SHADERPERMUTATION_SPECULAR;
1714                 if (r_refdef.fogenabled)
1715                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1716                 if (t->colormapping)
1717                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1718                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1719                 {
1720                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1721                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1722
1723                         if (r_shadow_shadowmap2ddepthbuffer)
1724                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1725                 }
1726                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1727                         permutation |= SHADERPERMUTATION_REFLECTION;
1728                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1729                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1730                 if (t->reflectmasktexture)
1731                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1732                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1733                 {
1734                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1735                         if (r_shadow_bouncegrid_state.directional)
1736                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1737                 }
1738                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1739                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1740                 // when using alphatocoverage, we don't need alphakill
1741                 if (vid.allowalphatocoverage)
1742                 {
1743                         if (r_transparent_alphatocoverage.integer)
1744                         {
1745                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1746                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1747                         }
1748                         else
1749                                 GL_AlphaToCoverage(false);
1750                 }
1751         }
1752         else
1753         {
1754                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
1755                 {
1756                         switch(t->offsetmapping)
1757                         {
1758                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
1759                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1760                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
1761                         case OFFSETMAPPING_OFF: break;
1762                         }
1763                 }
1764                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1765                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1766                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
1767                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
1768                 // lightmapped wall
1769                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1770                         permutation |= SHADERPERMUTATION_GLOW;
1771                 if (r_refdef.fogenabled)
1772                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
1773                 if (t->colormapping)
1774                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1775                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
1776                 {
1777                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
1778                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1779
1780                         if (r_shadow_shadowmap2ddepthbuffer)
1781                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1782                 }
1783                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
1784                         permutation |= SHADERPERMUTATION_REFLECTION;
1785                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
1786                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
1787                 if (t->reflectmasktexture)
1788                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
1789                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1790                 {
1791                         // deluxemapping (light direction texture)
1792                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1793                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1794                         else
1795                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1796                         permutation |= SHADERPERMUTATION_DIFFUSE;
1797                         if (VectorLength2(t->render_lightmap_specular) > 0)
1798                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1799                 }
1800                 else if (r_glsl_deluxemapping.integer >= 2)
1801                 {
1802                         // fake deluxemapping (uniform light direction in tangentspace)
1803                         if (rsurface.uselightmaptexture)
1804                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
1805                         else
1806                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
1807                         permutation |= SHADERPERMUTATION_DIFFUSE;
1808                         if (VectorLength2(t->render_lightmap_specular) > 0)
1809                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1810                 }
1811                 else if (rsurface.uselightmaptexture)
1812                 {
1813                         // ordinary lightmapping (q1bsp, q3bsp)
1814                         mode = SHADERMODE_LIGHTMAP;
1815                 }
1816                 else
1817                 {
1818                         // ordinary vertex coloring (q3bsp)
1819                         mode = SHADERMODE_VERTEXCOLOR;
1820                 }
1821                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
1822                 {
1823                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1824                         if (r_shadow_bouncegrid_state.directional)
1825                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1826                 }
1827                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1828                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
1829                 // when using alphatocoverage, we don't need alphakill
1830                 if (vid.allowalphatocoverage)
1831                 {
1832                         if (r_transparent_alphatocoverage.integer)
1833                         {
1834                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
1835                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
1836                         }
1837                         else
1838                                 GL_AlphaToCoverage(false);
1839                 }
1840         }
1841         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
1842                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
1843         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1844                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
1845         switch(vid.renderpath)
1846         {
1847         case RENDERPATH_GL32:
1848         case RENDERPATH_GLES2:
1849                 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);
1850                 RSurf_UploadBuffersForBatch();
1851                 // this has to be after RSurf_PrepareVerticesForBatch
1852                 if (rsurface.batchskeletaltransform3x4buffer)
1853                         permutation |= SHADERPERMUTATION_SKELETAL;
1854                 R_SetupShader_SetPermutationGLSL(mode, permutation);
1855 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1856                 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);
1857 #endif
1858                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
1859                 if (mode == SHADERMODE_LIGHTSOURCE)
1860                 {
1861                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
1862                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1863                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1864                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
1865                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
1866                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
1867         
1868                         // additive passes are only darkened by fog, not tinted
1869                         if (r_glsl_permutation->loc_FogColor >= 0)
1870                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1871                         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);
1872                 }
1873                 else
1874                 {
1875                         if (mode == SHADERMODE_FLATCOLOR)
1876                         {
1877                                 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]);
1878                         }
1879                         else if (mode == SHADERMODE_LIGHTDIRECTION)
1880                         {
1881                                 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]);
1882                                 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]);
1883                                 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]);
1884                                 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]);
1885                                 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]);
1886                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
1887                                 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]);
1888                         }
1889                         else
1890                         {
1891                                 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]);
1892                                 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]);
1893                                 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]);
1894                                 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]);
1895                                 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]);
1896                         }
1897                         // additive passes are only darkened by fog, not tinted
1898                         if (r_glsl_permutation->loc_FogColor >= 0)
1899                         {
1900                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
1901                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1902                                 else
1903                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1904                         }
1905                         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);
1906                         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]);
1907                         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]);
1908                         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);
1909                         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);
1910                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
1911                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
1912                         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);
1913                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
1914                 }
1915                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
1916                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
1917                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
1918                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
1919                 {
1920                         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]);
1921                         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]);
1922                 }
1923                 else
1924                 {
1925                         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]);
1926                         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]);
1927                 }
1928
1929                 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]);
1930                 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));
1931                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
1932                 if (r_glsl_permutation->loc_Color_Pants >= 0)
1933                 {
1934                         if (t->pantstexture)
1935                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
1936                         else
1937                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1938                 }
1939                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1940                 {
1941                         if (t->shirttexture)
1942                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
1943                         else
1944                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1945                 }
1946                 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]);
1947                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
1948                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
1949                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
1950                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
1951                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
1952                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1953                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
1954                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
1955                         );
1956                 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);
1957                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
1958                 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]);
1959                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
1960                 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);}
1961                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
1962
1963                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
1964                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
1966                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
1967                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
1968                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
1969                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
1970                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
1971                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
1972                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
1973                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
1974                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
1975                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
1976                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
1977                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
1978                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
1979                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
1980                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
1981                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
1982                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
1983                 if (rsurfacepass == RSURFPASS_BACKGROUND)
1984                 {
1985                         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);
1986                         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);
1987                         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);
1988                 }
1989                 else
1990                 {
1991                         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);
1992                 }
1993                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
1994                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
1995                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
1996                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
1997                 {
1998                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
1999                         if (rsurface.rtlight)
2000                         {
2001                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2002                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2003                         }
2004                 }
2005                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2006                 CHECKGLERROR
2007                 break;
2008         }
2009 }
2010
2011 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2012 {
2013         // select a permutation of the lighting shader appropriate to this
2014         // combination of texture, entity, light source, and fogging, only use the
2015         // minimum features necessary to avoid wasting rendering time in the
2016         // fragment shader on features that are not being used
2017         dpuint64 permutation = 0;
2018         unsigned int mode = 0;
2019         const float *lightcolorbase = rtlight->currentcolor;
2020         float ambientscale = rtlight->ambientscale;
2021         float diffusescale = rtlight->diffusescale;
2022         float specularscale = rtlight->specularscale;
2023         // this is the location of the light in view space
2024         vec3_t viewlightorigin;
2025         // this transforms from view space (camera) to light space (cubemap)
2026         matrix4x4_t viewtolight;
2027         matrix4x4_t lighttoview;
2028         float viewtolight16f[16];
2029         // light source
2030         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2031         if (rtlight->currentcubemap != r_texture_whitecube)
2032                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2033         if (diffusescale > 0)
2034                 permutation |= SHADERPERMUTATION_DIFFUSE;
2035         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2036                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2037         if (r_shadow_usingshadowmap2d)
2038         {
2039                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2040                 if (r_shadow_shadowmapvsdct)
2041                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2042
2043                 if (r_shadow_shadowmap2ddepthbuffer)
2044                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2045         }
2046         if (vid.allowalphatocoverage)
2047                 GL_AlphaToCoverage(false);
2048         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2049         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2050         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2051         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2052         switch(vid.renderpath)
2053         {
2054         case RENDERPATH_GL32:
2055         case RENDERPATH_GLES2:
2056                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2057                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2058                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2059                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
2060                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
2061                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
2062                 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]);
2063                 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]);
2064                 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);
2065                 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]);
2066                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2067
2068                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2069                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2070                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2071                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
2072                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2073                 break;
2074         }
2075 }
2076
2077 #define SKINFRAME_HASH 1024
2078
2079 typedef struct
2080 {
2081         unsigned int loadsequence; // incremented each level change
2082         memexpandablearray_t array;
2083         skinframe_t *hash[SKINFRAME_HASH];
2084 }
2085 r_skinframe_t;
2086 r_skinframe_t r_skinframe;
2087
2088 void R_SkinFrame_PrepareForPurge(void)
2089 {
2090         r_skinframe.loadsequence++;
2091         // wrap it without hitting zero
2092         if (r_skinframe.loadsequence >= 200)
2093                 r_skinframe.loadsequence = 1;
2094 }
2095
2096 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2097 {
2098         if (!skinframe)
2099                 return;
2100         // mark the skinframe as used for the purging code
2101         skinframe->loadsequence = r_skinframe.loadsequence;
2102 }
2103
2104 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
2105 {
2106         if (s == NULL)
2107                 return;
2108         if (s->merged == s->base)
2109                 s->merged = NULL;
2110         R_PurgeTexture(s->stain); s->stain = NULL;
2111         R_PurgeTexture(s->merged); s->merged = NULL;
2112         R_PurgeTexture(s->base); s->base = NULL;
2113         R_PurgeTexture(s->pants); s->pants = NULL;
2114         R_PurgeTexture(s->shirt); s->shirt = NULL;
2115         R_PurgeTexture(s->nmap); s->nmap = NULL;
2116         R_PurgeTexture(s->gloss); s->gloss = NULL;
2117         R_PurgeTexture(s->glow); s->glow = NULL;
2118         R_PurgeTexture(s->fog); s->fog = NULL;
2119         R_PurgeTexture(s->reflect); s->reflect = NULL;
2120         s->loadsequence = 0;
2121 }
2122
2123 void R_SkinFrame_Purge(void)
2124 {
2125         int i;
2126         skinframe_t *s;
2127         for (i = 0;i < SKINFRAME_HASH;i++)
2128         {
2129                 for (s = r_skinframe.hash[i];s;s = s->next)
2130                 {
2131                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2132                                 R_SkinFrame_PurgeSkinFrame(s);
2133                 }
2134         }
2135 }
2136
2137 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2138         skinframe_t *item;
2139         char basename[MAX_QPATH];
2140
2141         Image_StripImageExtension(name, basename, sizeof(basename));
2142
2143         if( last == NULL ) {
2144                 int hashindex;
2145                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2146                 item = r_skinframe.hash[hashindex];
2147         } else {
2148                 item = last->next;
2149         }
2150
2151         // linearly search through the hash bucket
2152         for( ; item ; item = item->next ) {
2153                 if( !strcmp( item->basename, basename ) ) {
2154                         return item;
2155                 }
2156         }
2157         return NULL;
2158 }
2159
2160 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2161 {
2162         skinframe_t *item;
2163         int compareflags = textureflags & TEXF_IMPORTANTBITS;
2164         int hashindex;
2165         char basename[MAX_QPATH];
2166
2167         Image_StripImageExtension(name, basename, sizeof(basename));
2168
2169         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2170         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2171                 if (!strcmp(item->basename, basename) &&
2172                         item->textureflags == compareflags &&
2173                         item->comparewidth == comparewidth &&
2174                         item->compareheight == compareheight &&
2175                         item->comparecrc == comparecrc)
2176                         break;
2177
2178         if (!item)
2179         {
2180                 if (!add)
2181                         return NULL;
2182                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2183                 memset(item, 0, sizeof(*item));
2184                 strlcpy(item->basename, basename, sizeof(item->basename));
2185                 item->textureflags = compareflags;
2186                 item->comparewidth = comparewidth;
2187                 item->compareheight = compareheight;
2188                 item->comparecrc = comparecrc;
2189                 item->next = r_skinframe.hash[hashindex];
2190                 r_skinframe.hash[hashindex] = item;
2191         }
2192         else if (textureflags & TEXF_FORCE_RELOAD)
2193                 R_SkinFrame_PurgeSkinFrame(item);
2194
2195         R_SkinFrame_MarkUsed(item);
2196         return item;
2197 }
2198
2199 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2200         { \
2201                 unsigned long long avgcolor[5], wsum; \
2202                 int pix, comp, w; \
2203                 avgcolor[0] = 0; \
2204                 avgcolor[1] = 0; \
2205                 avgcolor[2] = 0; \
2206                 avgcolor[3] = 0; \
2207                 avgcolor[4] = 0; \
2208                 wsum = 0; \
2209                 for(pix = 0; pix < cnt; ++pix) \
2210                 { \
2211                         w = 0; \
2212                         for(comp = 0; comp < 3; ++comp) \
2213                                 w += getpixel; \
2214                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2215                         { \
2216                                 ++wsum; \
2217                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2218                                 w = getpixel; \
2219                                 for(comp = 0; comp < 3; ++comp) \
2220                                         avgcolor[comp] += getpixel * w; \
2221                                 avgcolor[3] += w; \
2222                         } \
2223                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2224                         avgcolor[4] += getpixel; \
2225                 } \
2226                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2227                         avgcolor[3] = 1; \
2228                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2229                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2230                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2231                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2232         }
2233
2234 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2235 {
2236         skinframe_t *skinframe;
2237
2238         if (cls.state == ca_dedicated)
2239                 return NULL;
2240
2241         // return an existing skinframe if already loaded
2242         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2243         if (skinframe && skinframe->base)
2244                 return skinframe;
2245
2246         // if the skinframe doesn't exist this will create it
2247         return R_SkinFrame_LoadExternal_SkinFrame(skinframe, name, textureflags, complain, fallbacknotexture);
2248 }
2249
2250 extern cvar_t gl_picmip;
2251 skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
2252 {
2253         int j;
2254         unsigned char *pixels;
2255         unsigned char *bumppixels;
2256         unsigned char *basepixels = NULL;
2257         int basepixels_width = 0;
2258         int basepixels_height = 0;
2259         rtexture_t *ddsbase = NULL;
2260         qboolean ddshasalpha = false;
2261         float ddsavgcolor[4];
2262         char basename[MAX_QPATH];
2263         int miplevel = R_PicmipForFlags(textureflags);
2264         int savemiplevel = miplevel;
2265         int mymiplevel;
2266         char vabuf[1024];
2267
2268         if (cls.state == ca_dedicated)
2269                 return NULL;
2270
2271         Image_StripImageExtension(name, basename, sizeof(basename));
2272
2273         // check for DDS texture file first
2274         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
2275         {
2276                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
2277                 if (basepixels == NULL && fallbacknotexture)
2278                         basepixels = Image_GenerateNoTexture();
2279                 if (basepixels == NULL)
2280                         return NULL;
2281         }
2282
2283         // FIXME handle miplevel
2284
2285         if (developer_loading.integer)
2286                 Con_Printf("loading skin \"%s\"\n", name);
2287
2288         // we've got some pixels to store, so really allocate this new texture now
2289         if (!skinframe)
2290                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2291         textureflags &= ~TEXF_FORCE_RELOAD;
2292         skinframe->stain = NULL;
2293         skinframe->merged = NULL;
2294         skinframe->base = NULL;
2295         skinframe->pants = NULL;
2296         skinframe->shirt = NULL;
2297         skinframe->nmap = NULL;
2298         skinframe->gloss = NULL;
2299         skinframe->glow = NULL;
2300         skinframe->fog = NULL;
2301         skinframe->reflect = NULL;
2302         skinframe->hasalpha = false;
2303         // we could store the q2animname here too
2304
2305         if (ddsbase)
2306         {
2307                 skinframe->base = ddsbase;
2308                 skinframe->hasalpha = ddshasalpha;
2309                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
2310                 if (r_loadfog && skinframe->hasalpha)
2311                         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);
2312                 //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]);
2313         }
2314         else
2315         {
2316                 basepixels_width = image_width;
2317                 basepixels_height = image_height;
2318                 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);
2319                 if (textureflags & TEXF_ALPHA)
2320                 {
2321                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2322                         {
2323                                 if (basepixels[j] < 255)
2324                                 {
2325                                         skinframe->hasalpha = true;
2326                                         break;
2327                                 }
2328                         }
2329                         if (r_loadfog && skinframe->hasalpha)
2330                         {
2331                                 // has transparent pixels
2332                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2333                                 for (j = 0;j < image_width * image_height * 4;j += 4)
2334                                 {
2335                                         pixels[j+0] = 255;
2336                                         pixels[j+1] = 255;
2337                                         pixels[j+2] = 255;
2338                                         pixels[j+3] = basepixels[j+3];
2339                                 }
2340                                 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);
2341                                 Mem_Free(pixels);
2342                         }
2343                 }
2344                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2345 #ifndef USE_GLES2
2346                 //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]);
2347                 if (r_savedds && skinframe->base)
2348                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
2349                 if (r_savedds && skinframe->fog)
2350                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2351 #endif
2352         }
2353
2354         if (r_loaddds)
2355         {
2356                 mymiplevel = savemiplevel;
2357                 if (r_loadnormalmap)
2358                         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);
2359                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2360                 if (r_loadgloss)
2361                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2362                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2363                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2364                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
2365         }
2366
2367         // _norm is the name used by tenebrae and has been adopted as standard
2368         if (r_loadnormalmap && skinframe->nmap == NULL)
2369         {
2370                 mymiplevel = savemiplevel;
2371                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2372                 {
2373                         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);
2374                         Mem_Free(pixels);
2375                         pixels = NULL;
2376                 }
2377                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
2378                 {
2379                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2380                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2381                         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);
2382                         Mem_Free(pixels);
2383                         Mem_Free(bumppixels);
2384                 }
2385                 else if (r_shadow_bumpscale_basetexture.value > 0)
2386                 {
2387                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2388                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2389                         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);
2390                         Mem_Free(pixels);
2391                 }
2392 #ifndef USE_GLES2
2393                 if (r_savedds && skinframe->nmap)
2394                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2395 #endif
2396         }
2397
2398         // _luma is supported only for tenebrae compatibility
2399         // _glow is the preferred name
2400         mymiplevel = savemiplevel;
2401         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))))
2402         {
2403                 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);
2404 #ifndef USE_GLES2
2405                 if (r_savedds && skinframe->glow)
2406                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2407 #endif
2408                 Mem_Free(pixels);pixels = NULL;
2409         }
2410
2411         mymiplevel = savemiplevel;
2412         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
2413         {
2414                 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);
2415 #ifndef USE_GLES2
2416                 if (r_savedds && skinframe->gloss)
2417                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2418 #endif
2419                 Mem_Free(pixels);
2420                 pixels = NULL;
2421         }
2422
2423         mymiplevel = savemiplevel;
2424         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
2425         {
2426                 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);
2427 #ifndef USE_GLES2
2428                 if (r_savedds && skinframe->pants)
2429                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2430 #endif
2431                 Mem_Free(pixels);
2432                 pixels = NULL;
2433         }
2434
2435         mymiplevel = savemiplevel;
2436         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
2437         {
2438                 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);
2439 #ifndef USE_GLES2
2440                 if (r_savedds && skinframe->shirt)
2441                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
2442 #endif
2443                 Mem_Free(pixels);
2444                 pixels = NULL;
2445         }
2446
2447         mymiplevel = savemiplevel;
2448         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
2449         {
2450                 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);
2451 #ifndef USE_GLES2
2452                 if (r_savedds && skinframe->reflect)
2453                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
2454 #endif
2455                 Mem_Free(pixels);
2456                 pixels = NULL;
2457         }
2458
2459         if (basepixels)
2460                 Mem_Free(basepixels);
2461
2462         return skinframe;
2463 }
2464
2465 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)
2466 {
2467         int i;
2468         skinframe_t *skinframe;
2469         char vabuf[1024];
2470
2471         if (cls.state == ca_dedicated)
2472                 return NULL;
2473
2474         // if already loaded just return it, otherwise make a new skinframe
2475         skinframe = R_SkinFrame_Find(name, textureflags, comparewidth, compareheight, comparecrc, true);
2476         if (skinframe->base)
2477                 return skinframe;
2478         textureflags &= ~TEXF_FORCE_RELOAD;
2479
2480         skinframe->stain = NULL;
2481         skinframe->merged = NULL;
2482         skinframe->base = NULL;
2483         skinframe->pants = NULL;
2484         skinframe->shirt = NULL;
2485         skinframe->nmap = NULL;
2486         skinframe->gloss = NULL;
2487         skinframe->glow = NULL;
2488         skinframe->fog = NULL;
2489         skinframe->reflect = NULL;
2490         skinframe->hasalpha = false;
2491
2492         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2493         if (!skindata)
2494                 return NULL;
2495
2496         if (developer_loading.integer)
2497                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2498
2499         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2500         {
2501                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2502                 unsigned char *b = a + width * height * 4;
2503                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2504                 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);
2505                 Mem_Free(a);
2506         }
2507         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
2508         if (textureflags & TEXF_ALPHA)
2509         {
2510                 for (i = 3;i < width * height * 4;i += 4)
2511                 {
2512                         if (skindata[i] < 255)
2513                         {
2514                                 skinframe->hasalpha = true;
2515                                 break;
2516                         }
2517                 }
2518                 if (r_loadfog && skinframe->hasalpha)
2519                 {
2520                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2521                         memcpy(fogpixels, skindata, width * height * 4);
2522                         for (i = 0;i < width * height * 4;i += 4)
2523                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2524                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
2525                         Mem_Free(fogpixels);
2526                 }
2527         }
2528
2529         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2530         //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]);
2531
2532         return skinframe;
2533 }
2534
2535 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2536 {
2537         int i;
2538         int featuresmask;
2539         skinframe_t *skinframe;
2540
2541         if (cls.state == ca_dedicated)
2542                 return NULL;
2543
2544         // if already loaded just return it, otherwise make a new skinframe
2545         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2546         if (skinframe->base)
2547                 return skinframe;
2548         //textureflags &= ~TEXF_FORCE_RELOAD;
2549
2550         skinframe->stain = NULL;
2551         skinframe->merged = NULL;
2552         skinframe->base = NULL;
2553         skinframe->pants = NULL;
2554         skinframe->shirt = NULL;
2555         skinframe->nmap = NULL;
2556         skinframe->gloss = NULL;
2557         skinframe->glow = NULL;
2558         skinframe->fog = NULL;
2559         skinframe->reflect = NULL;
2560         skinframe->hasalpha = false;
2561
2562         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2563         if (!skindata)
2564                 return NULL;
2565
2566         if (developer_loading.integer)
2567                 Con_Printf("loading quake skin \"%s\"\n", name);
2568
2569         // 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)
2570         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
2571         memcpy(skinframe->qpixels, skindata, width*height);
2572         skinframe->qwidth = width;
2573         skinframe->qheight = height;
2574
2575         featuresmask = 0;
2576         for (i = 0;i < width * height;i++)
2577                 featuresmask |= palette_featureflags[skindata[i]];
2578
2579         skinframe->hasalpha = false;
2580         // fence textures
2581         if (name[0] == '{')
2582                 skinframe->hasalpha = true;
2583         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2584         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2585         skinframe->qgeneratemerged = true;
2586         skinframe->qgeneratebase = skinframe->qhascolormapping;
2587         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2588
2589         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2590         //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]);
2591
2592         return skinframe;
2593 }
2594
2595 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2596 {
2597         int width;
2598         int height;
2599         unsigned char *skindata;
2600         char vabuf[1024];
2601
2602         if (!skinframe->qpixels)
2603                 return;
2604
2605         if (!skinframe->qhascolormapping)
2606                 colormapped = false;
2607
2608         if (colormapped)
2609         {
2610                 if (!skinframe->qgeneratebase)
2611                         return;
2612         }
2613         else
2614         {
2615                 if (!skinframe->qgeneratemerged)
2616                         return;
2617         }
2618
2619         width = skinframe->qwidth;
2620         height = skinframe->qheight;
2621         skindata = skinframe->qpixels;
2622
2623         if (skinframe->qgeneratenmap)
2624         {
2625                 unsigned char *a, *b;
2626                 skinframe->qgeneratenmap = false;
2627                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2628                 b = a + width * height * 4;
2629                 // use either a custom palette or the quake palette
2630                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
2631                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
2632                 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);
2633                 Mem_Free(a);
2634         }
2635
2636         if (skinframe->qgenerateglow)
2637         {
2638                 skinframe->qgenerateglow = false;
2639                 if (skinframe->hasalpha) // fence textures
2640                         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
2641                 else
2642                         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
2643         }
2644
2645         if (colormapped)
2646         {
2647                 skinframe->qgeneratebase = false;
2648                 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);
2649                 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);
2650                 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);
2651         }
2652         else
2653         {
2654                 skinframe->qgeneratemerged = false;
2655                 if (skinframe->hasalpha) // fence textures
2656                         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);
2657                 else
2658                         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);
2659         }
2660
2661         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2662         {
2663                 Mem_Free(skinframe->qpixels);
2664                 skinframe->qpixels = NULL;
2665         }
2666 }
2667
2668 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)
2669 {
2670         int i;
2671         skinframe_t *skinframe;
2672         char vabuf[1024];
2673
2674         if (cls.state == ca_dedicated)
2675                 return NULL;
2676
2677         // if already loaded just return it, otherwise make a new skinframe
2678         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2679         if (skinframe->base)
2680                 return skinframe;
2681         textureflags &= ~TEXF_FORCE_RELOAD;
2682
2683         skinframe->stain = NULL;
2684         skinframe->merged = NULL;
2685         skinframe->base = NULL;
2686         skinframe->pants = NULL;
2687         skinframe->shirt = NULL;
2688         skinframe->nmap = NULL;
2689         skinframe->gloss = NULL;
2690         skinframe->glow = NULL;
2691         skinframe->fog = NULL;
2692         skinframe->reflect = NULL;
2693         skinframe->hasalpha = false;
2694
2695         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2696         if (!skindata)
2697                 return NULL;
2698
2699         if (developer_loading.integer)
2700                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2701
2702         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
2703         if ((textureflags & TEXF_ALPHA) && alphapalette)
2704         {
2705                 for (i = 0;i < width * height;i++)
2706                 {
2707                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2708                         {
2709                                 skinframe->hasalpha = true;
2710                                 break;
2711                         }
2712                 }
2713                 if (r_loadfog && skinframe->hasalpha)
2714                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
2715         }
2716
2717         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2718         //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]);
2719
2720         return skinframe;
2721 }
2722
2723 skinframe_t *R_SkinFrame_LoadMissing(void)
2724 {
2725         skinframe_t *skinframe;
2726
2727         if (cls.state == ca_dedicated)
2728                 return NULL;
2729
2730         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
2731         skinframe->stain = NULL;
2732         skinframe->merged = NULL;
2733         skinframe->base = NULL;
2734         skinframe->pants = NULL;
2735         skinframe->shirt = NULL;
2736         skinframe->nmap = NULL;
2737         skinframe->gloss = NULL;
2738         skinframe->glow = NULL;
2739         skinframe->fog = NULL;
2740         skinframe->reflect = NULL;
2741         skinframe->hasalpha = false;
2742
2743         skinframe->avgcolor[0] = rand() / RAND_MAX;
2744         skinframe->avgcolor[1] = rand() / RAND_MAX;
2745         skinframe->avgcolor[2] = rand() / RAND_MAX;
2746         skinframe->avgcolor[3] = 1;
2747
2748         return skinframe;
2749 }
2750
2751 skinframe_t *R_SkinFrame_LoadNoTexture(void)
2752 {
2753         int x, y;
2754         static unsigned char pix[16][16][4];
2755
2756         if (cls.state == ca_dedicated)
2757                 return NULL;
2758
2759         // this makes a light grey/dark grey checkerboard texture
2760         if (!pix[0][0][3])
2761         {
2762                 for (y = 0; y < 16; y++)
2763                 {
2764                         for (x = 0; x < 16; x++)
2765                         {
2766                                 if ((y < 8) ^ (x < 8))
2767                                 {
2768                                         pix[y][x][0] = 128;
2769                                         pix[y][x][1] = 128;
2770                                         pix[y][x][2] = 128;
2771                                         pix[y][x][3] = 255;
2772                                 }
2773                                 else
2774                                 {
2775                                         pix[y][x][0] = 64;
2776                                         pix[y][x][1] = 64;
2777                                         pix[y][x][2] = 64;
2778                                         pix[y][x][3] = 255;
2779                                 }
2780                         }
2781                 }
2782         }
2783
2784         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, 0, 0, 0, false);
2785 }
2786
2787 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
2788 {
2789         skinframe_t *skinframe;
2790         if (cls.state == ca_dedicated)
2791                 return NULL;
2792         // if already loaded just return it, otherwise make a new skinframe
2793         skinframe = R_SkinFrame_Find(name, textureflags, width, height, 0, true);
2794         if (skinframe->base)
2795                 return skinframe;
2796         textureflags &= ~TEXF_FORCE_RELOAD;
2797         skinframe->stain = NULL;
2798         skinframe->merged = NULL;
2799         skinframe->base = NULL;
2800         skinframe->pants = NULL;
2801         skinframe->shirt = NULL;
2802         skinframe->nmap = NULL;
2803         skinframe->gloss = NULL;
2804         skinframe->glow = NULL;
2805         skinframe->fog = NULL;
2806         skinframe->reflect = NULL;
2807         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
2808         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2809         if (!tex)
2810                 return NULL;
2811         if (developer_loading.integer)
2812                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2813         skinframe->base = skinframe->merged = tex;
2814         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
2815         return skinframe;
2816 }
2817
2818 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
2819 typedef struct suffixinfo_s
2820 {
2821         const char *suffix;
2822         qboolean flipx, flipy, flipdiagonal;
2823 }
2824 suffixinfo_t;
2825 static suffixinfo_t suffix[3][6] =
2826 {
2827         {
2828                 {"px",   false, false, false},
2829                 {"nx",   false, false, false},
2830                 {"py",   false, false, false},
2831                 {"ny",   false, false, false},
2832                 {"pz",   false, false, false},
2833                 {"nz",   false, false, false}
2834         },
2835         {
2836                 {"posx", false, false, false},
2837                 {"negx", false, false, false},
2838                 {"posy", false, false, false},
2839                 {"negy", false, false, false},
2840                 {"posz", false, false, false},
2841                 {"negz", false, false, false}
2842         },
2843         {
2844                 {"rt",    true, false,  true},
2845                 {"lf",   false,  true,  true},
2846                 {"ft",    true,  true, false},
2847                 {"bk",   false, false, false},
2848                 {"up",    true, false,  true},
2849                 {"dn",    true, false,  true}
2850         }
2851 };
2852
2853 static int componentorder[4] = {0, 1, 2, 3};
2854
2855 static rtexture_t *R_LoadCubemap(const char *basename)
2856 {
2857         int i, j, cubemapsize;
2858         unsigned char *cubemappixels, *image_buffer;
2859         rtexture_t *cubemaptexture;
2860         char name[256];
2861         // must start 0 so the first loadimagepixels has no requested width/height
2862         cubemapsize = 0;
2863         cubemappixels = NULL;
2864         cubemaptexture = NULL;
2865         // keep trying different suffix groups (posx, px, rt) until one loads
2866         for (j = 0;j < 3 && !cubemappixels;j++)
2867         {
2868                 // load the 6 images in the suffix group
2869                 for (i = 0;i < 6;i++)
2870                 {
2871                         // generate an image name based on the base and and suffix
2872                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
2873                         // load it
2874                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
2875                         {
2876                                 // an image loaded, make sure width and height are equal
2877                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
2878                                 {
2879                                         // if this is the first image to load successfully, allocate the cubemap memory
2880                                         if (!cubemappixels && image_width >= 1)
2881                                         {
2882                                                 cubemapsize = image_width;
2883                                                 // note this clears to black, so unavailable sides are black
2884                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
2885                                         }
2886                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
2887                                         if (cubemappixels)
2888                                                 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);
2889                                 }
2890                                 else
2891                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
2892                                 // free the image
2893                                 Mem_Free(image_buffer);
2894                         }
2895                 }
2896         }
2897         // if a cubemap loaded, upload it
2898         if (cubemappixels)
2899         {
2900                 if (developer_loading.integer)
2901                         Con_Printf("loading cubemap \"%s\"\n", basename);
2902
2903                 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);
2904                 Mem_Free(cubemappixels);
2905         }
2906         else
2907         {
2908                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
2909                 if (developer_loading.integer)
2910                 {
2911                         Con_Printf("(tried tried images ");
2912                         for (j = 0;j < 3;j++)
2913                                 for (i = 0;i < 6;i++)
2914                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
2915                         Con_Print(" and was unable to find any of them).\n");
2916                 }
2917         }
2918         return cubemaptexture;
2919 }
2920
2921 rtexture_t *R_GetCubemap(const char *basename)
2922 {
2923         int i;
2924         for (i = 0;i < r_texture_numcubemaps;i++)
2925                 if (r_texture_cubemaps[i] != NULL)
2926                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
2927                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
2928         if (i >= MAX_CUBEMAPS || !r_main_mempool)
2929                 return r_texture_whitecube;
2930         r_texture_numcubemaps++;
2931         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
2932         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
2933         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
2934         return r_texture_cubemaps[i]->texture;
2935 }
2936
2937 static void R_Main_FreeViewCache(void)
2938 {
2939         if (r_refdef.viewcache.entityvisible)
2940                 Mem_Free(r_refdef.viewcache.entityvisible);
2941         if (r_refdef.viewcache.world_pvsbits)
2942                 Mem_Free(r_refdef.viewcache.world_pvsbits);
2943         if (r_refdef.viewcache.world_leafvisible)
2944                 Mem_Free(r_refdef.viewcache.world_leafvisible);
2945         if (r_refdef.viewcache.world_surfacevisible)
2946                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2947         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2948 }
2949
2950 static void R_Main_ResizeViewCache(void)
2951 {
2952         int numentities = r_refdef.scene.numentities;
2953         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2954         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2955         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2956         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2957         if (r_refdef.viewcache.maxentities < numentities)
2958         {
2959                 r_refdef.viewcache.maxentities = numentities;
2960                 if (r_refdef.viewcache.entityvisible)
2961                         Mem_Free(r_refdef.viewcache.entityvisible);
2962                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2963         }
2964         if (r_refdef.viewcache.world_numclusters != numclusters)
2965         {
2966                 r_refdef.viewcache.world_numclusters = numclusters;
2967                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2968                 if (r_refdef.viewcache.world_pvsbits)
2969                         Mem_Free(r_refdef.viewcache.world_pvsbits);
2970                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2971         }
2972         if (r_refdef.viewcache.world_numleafs != numleafs)
2973         {
2974                 r_refdef.viewcache.world_numleafs = numleafs;
2975                 if (r_refdef.viewcache.world_leafvisible)
2976                         Mem_Free(r_refdef.viewcache.world_leafvisible);
2977                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2978         }
2979         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2980         {
2981                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2982                 if (r_refdef.viewcache.world_surfacevisible)
2983                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
2984                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2985         }
2986 }
2987
2988 extern rtexture_t *loadingscreentexture;
2989 static void gl_main_start(void)
2990 {
2991         loadingscreentexture = NULL;
2992         r_texture_blanknormalmap = NULL;
2993         r_texture_white = NULL;
2994         r_texture_grey128 = NULL;
2995         r_texture_black = NULL;
2996         r_texture_whitecube = NULL;
2997         r_texture_normalizationcube = NULL;
2998         r_texture_fogattenuation = NULL;
2999         r_texture_fogheighttexture = NULL;
3000         r_texture_gammaramps = NULL;
3001         r_texture_numcubemaps = 0;
3002         r_uniformbufferalignment = 32;
3003
3004         r_loaddds = r_texture_dds_load.integer != 0;
3005         r_savedds = vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3006
3007         switch(vid.renderpath)
3008         {
3009         case RENDERPATH_GL32:
3010         case RENDERPATH_GLES2:
3011                 Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS);
3012                 Cvar_SetValueQuick(&gl_combine, 1);
3013                 Cvar_SetValueQuick(&r_glsl, 1);
3014                 r_loadnormalmap = true;
3015                 r_loadgloss = true;
3016                 r_loadfog = false;
3017 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3018                 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3019 #endif
3020                 break;
3021         }
3022
3023         R_AnimCache_Free();
3024         R_FrameData_Reset();
3025         R_BufferData_Reset();
3026
3027         r_numqueries = 0;
3028         r_maxqueries = 0;
3029         memset(r_queries, 0, sizeof(r_queries));
3030
3031         r_qwskincache = NULL;
3032         r_qwskincache_size = 0;
3033
3034         // due to caching of texture_t references, the collision cache must be reset
3035         Collision_Cache_Reset(true);
3036
3037         // set up r_skinframe loading system for textures
3038         memset(&r_skinframe, 0, sizeof(r_skinframe));
3039         r_skinframe.loadsequence = 1;
3040         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3041
3042         r_main_texturepool = R_AllocTexturePool();
3043         R_BuildBlankTextures();
3044         R_BuildNoTexture();
3045         R_BuildWhiteCube();
3046         R_BuildNormalizationCube();
3047         r_texture_fogattenuation = NULL;
3048         r_texture_fogheighttexture = NULL;
3049         r_texture_gammaramps = NULL;
3050         //r_texture_fogintensity = NULL;
3051         memset(&r_fb, 0, sizeof(r_fb));
3052         Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
3053         r_glsl_permutation = NULL;
3054         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3055         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3056         memset(&r_svbsp, 0, sizeof (r_svbsp));
3057
3058         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3059         r_texture_numcubemaps = 0;
3060
3061         r_refdef.fogmasktable_density = 0;
3062
3063 #ifdef __ANDROID__
3064         // For Steelstorm Android
3065         // FIXME CACHE the program and reload
3066         // FIXME see possible combinations for SS:BR android
3067         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
3068         R_SetupShader_SetPermutationGLSL(0, 12);
3069         R_SetupShader_SetPermutationGLSL(0, 13);
3070         R_SetupShader_SetPermutationGLSL(0, 8388621);
3071         R_SetupShader_SetPermutationGLSL(3, 0);
3072         R_SetupShader_SetPermutationGLSL(3, 2048);
3073         R_SetupShader_SetPermutationGLSL(5, 0);
3074         R_SetupShader_SetPermutationGLSL(5, 2);
3075         R_SetupShader_SetPermutationGLSL(5, 2048);
3076         R_SetupShader_SetPermutationGLSL(5, 8388608);
3077         R_SetupShader_SetPermutationGLSL(11, 1);
3078         R_SetupShader_SetPermutationGLSL(11, 2049);
3079         R_SetupShader_SetPermutationGLSL(11, 8193);
3080         R_SetupShader_SetPermutationGLSL(11, 10241);
3081         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
3082 #endif
3083 }
3084
3085 static void gl_main_shutdown(void)
3086 {
3087         R_RenderTarget_FreeUnused(true);
3088         Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
3089         R_AnimCache_Free();
3090         R_FrameData_Reset();
3091         R_BufferData_Reset();
3092
3093         R_Main_FreeViewCache();
3094
3095         switch(vid.renderpath)
3096         {
3097         case RENDERPATH_GL32:
3098         case RENDERPATH_GLES2:
3099 #if defined(GL_SAMPLES_PASSED) && !defined(USE_GLES2)
3100                 if (r_maxqueries)
3101                         qglDeleteQueries(r_maxqueries, r_queries);
3102 #endif
3103                 break;
3104         }
3105
3106         r_numqueries = 0;
3107         r_maxqueries = 0;
3108         memset(r_queries, 0, sizeof(r_queries));
3109
3110         r_qwskincache = NULL;
3111         r_qwskincache_size = 0;
3112
3113         // clear out the r_skinframe state
3114         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3115         memset(&r_skinframe, 0, sizeof(r_skinframe));
3116
3117         if (r_svbsp.nodes)
3118                 Mem_Free(r_svbsp.nodes);
3119         memset(&r_svbsp, 0, sizeof (r_svbsp));
3120         R_FreeTexturePool(&r_main_texturepool);
3121         loadingscreentexture = NULL;
3122         r_texture_blanknormalmap = NULL;
3123         r_texture_white = NULL;
3124         r_texture_grey128 = NULL;
3125         r_texture_black = NULL;
3126         r_texture_whitecube = NULL;
3127         r_texture_normalizationcube = NULL;
3128         r_texture_fogattenuation = NULL;
3129         r_texture_fogheighttexture = NULL;
3130         r_texture_gammaramps = NULL;
3131         r_texture_numcubemaps = 0;
3132         //r_texture_fogintensity = NULL;
3133         memset(&r_fb, 0, sizeof(r_fb));
3134         R_GLSL_Restart_f();
3135
3136         r_glsl_permutation = NULL;
3137         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3138         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3139 }
3140
3141 static void gl_main_newmap(void)
3142 {
3143         // FIXME: move this code to client
3144         char *entities, entname[MAX_QPATH];
3145         if (r_qwskincache)
3146                 Mem_Free(r_qwskincache);
3147         r_qwskincache = NULL;
3148         r_qwskincache_size = 0;
3149         if (cl.worldmodel)
3150         {
3151                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3152                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3153                 {
3154                         CL_ParseEntityLump(entities);
3155                         Mem_Free(entities);
3156                         return;
3157                 }
3158                 if (cl.worldmodel->brush.entities)
3159                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3160         }
3161         R_Main_FreeViewCache();
3162
3163         R_FrameData_Reset();
3164         R_BufferData_Reset();
3165 }
3166
3167 void GL_Main_Init(void)
3168 {
3169         int i;
3170         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3171         R_InitShaderModeInfo();
3172
3173         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3174         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3175         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3176         if (gamemode == GAME_NEHAHRA)
3177         {
3178                 Cvar_RegisterVariable (&gl_fogenable);
3179                 Cvar_RegisterVariable (&gl_fogdensity);
3180                 Cvar_RegisterVariable (&gl_fogred);
3181                 Cvar_RegisterVariable (&gl_foggreen);
3182                 Cvar_RegisterVariable (&gl_fogblue);
3183                 Cvar_RegisterVariable (&gl_fogstart);
3184                 Cvar_RegisterVariable (&gl_fogend);
3185                 Cvar_RegisterVariable (&gl_skyclip);
3186         }
3187         Cvar_RegisterVariable(&r_motionblur);
3188         Cvar_RegisterVariable(&r_damageblur);
3189         Cvar_RegisterVariable(&r_motionblur_averaging);
3190         Cvar_RegisterVariable(&r_motionblur_randomize);
3191         Cvar_RegisterVariable(&r_motionblur_minblur);
3192         Cvar_RegisterVariable(&r_motionblur_maxblur);
3193         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
3194         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
3195         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
3196         Cvar_RegisterVariable(&r_motionblur_mousefactor);
3197         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
3198         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
3199         Cvar_RegisterVariable(&r_depthfirst);
3200         Cvar_RegisterVariable(&r_useinfinitefarclip);
3201         Cvar_RegisterVariable(&r_farclip_base);
3202         Cvar_RegisterVariable(&r_farclip_world);
3203         Cvar_RegisterVariable(&r_nearclip);
3204         Cvar_RegisterVariable(&r_deformvertexes);
3205         Cvar_RegisterVariable(&r_transparent);
3206         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
3207         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
3208         Cvar_RegisterVariable(&r_transparent_useplanardistance);
3209         Cvar_RegisterVariable(&r_showoverdraw);
3210         Cvar_RegisterVariable(&r_showbboxes);
3211         Cvar_RegisterVariable(&r_showbboxes_client);
3212         Cvar_RegisterVariable(&r_showsurfaces);
3213         Cvar_RegisterVariable(&r_showtris);
3214         Cvar_RegisterVariable(&r_shownormals);
3215         Cvar_RegisterVariable(&r_showlighting);
3216         Cvar_RegisterVariable(&r_showcollisionbrushes);
3217         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3218         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3219         Cvar_RegisterVariable(&r_showdisabledepthtest);
3220         Cvar_RegisterVariable(&r_showspriteedges);
3221         Cvar_RegisterVariable(&r_showparticleedges);
3222         Cvar_RegisterVariable(&r_drawportals);
3223         Cvar_RegisterVariable(&r_drawentities);
3224         Cvar_RegisterVariable(&r_draw2d);
3225         Cvar_RegisterVariable(&r_drawworld);
3226         Cvar_RegisterVariable(&r_cullentities_trace);
3227         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
3228         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3229         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3230         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3231         Cvar_RegisterVariable(&r_cullentities_trace_expand);
3232         Cvar_RegisterVariable(&r_cullentities_trace_pad);
3233         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3234         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
3235         Cvar_RegisterVariable(&r_sortentities);
3236         Cvar_RegisterVariable(&r_drawviewmodel);
3237         Cvar_RegisterVariable(&r_drawexteriormodel);
3238         Cvar_RegisterVariable(&r_speeds);
3239         Cvar_RegisterVariable(&r_fullbrights);
3240         Cvar_RegisterVariable(&r_wateralpha);
3241         Cvar_RegisterVariable(&r_dynamic);
3242         Cvar_RegisterVariable(&r_fullbright_directed);
3243         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
3244         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
3245         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
3246         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
3247         Cvar_RegisterVariable(&r_fullbright);
3248         Cvar_RegisterVariable(&r_shadows);
3249         Cvar_RegisterVariable(&r_shadows_darken);
3250         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3251         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3252         Cvar_RegisterVariable(&r_shadows_throwdistance);
3253         Cvar_RegisterVariable(&r_shadows_throwdirection);
3254         Cvar_RegisterVariable(&r_shadows_focus);
3255         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
3256         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
3257         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3258         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3259         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3260         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3261         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3262         Cvar_RegisterVariable(&r_fog_exp2);
3263         Cvar_RegisterVariable(&r_fog_clear);
3264         Cvar_RegisterVariable(&r_drawfog);
3265         Cvar_RegisterVariable(&r_transparentdepthmasking);
3266         Cvar_RegisterVariable(&r_transparent_sortmindist);
3267         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
3268         Cvar_RegisterVariable(&r_transparent_sortarraysize);
3269         Cvar_RegisterVariable(&r_texture_dds_load);
3270         Cvar_RegisterVariable(&r_texture_dds_save);
3271         Cvar_RegisterVariable(&r_textureunits);
3272         Cvar_RegisterVariable(&gl_combine);
3273         Cvar_RegisterVariable(&r_usedepthtextures);
3274         Cvar_RegisterVariable(&r_viewfbo);
3275         Cvar_RegisterVariable(&r_rendertarget_debug);
3276         Cvar_RegisterVariable(&r_viewscale);
3277         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
3278         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
3279         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
3280         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
3281         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
3282         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
3283         Cvar_RegisterVariable(&r_glsl);
3284         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3285         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3286         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
3287         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3288         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
3289         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
3290         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3291         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
3292         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
3293         Cvar_RegisterVariable(&r_glsl_postprocess);
3294         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3295         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3296         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3297         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3298         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
3299         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
3300         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
3301         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
3302         Cvar_RegisterVariable(&r_celshading);
3303         Cvar_RegisterVariable(&r_celoutlines);
3304
3305         Cvar_RegisterVariable(&r_water);
3306         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
3307         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3308         Cvar_RegisterVariable(&r_water_clippingplanebias);
3309         Cvar_RegisterVariable(&r_water_refractdistort);
3310         Cvar_RegisterVariable(&r_water_reflectdistort);
3311         Cvar_RegisterVariable(&r_water_scissormode);
3312         Cvar_RegisterVariable(&r_water_lowquality);
3313         Cvar_RegisterVariable(&r_water_hideplayer);
3314
3315         Cvar_RegisterVariable(&r_lerpsprites);
3316         Cvar_RegisterVariable(&r_lerpmodels);
3317         Cvar_RegisterVariable(&r_lerplightstyles);
3318         Cvar_RegisterVariable(&r_waterscroll);
3319         Cvar_RegisterVariable(&r_bloom);
3320         Cvar_RegisterVariable(&r_bloom_colorscale);
3321         Cvar_RegisterVariable(&r_bloom_brighten);
3322         Cvar_RegisterVariable(&r_bloom_blur);
3323         Cvar_RegisterVariable(&r_bloom_resolution);
3324         Cvar_RegisterVariable(&r_bloom_colorexponent);
3325         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3326         Cvar_RegisterVariable(&r_bloom_scenebrightness);
3327         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3328         Cvar_RegisterVariable(&r_hdr_glowintensity);
3329         Cvar_RegisterVariable(&r_hdr_irisadaptation);
3330         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
3331         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
3332         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
3333         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
3334         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
3335         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
3336         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
3337         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3338         Cvar_RegisterVariable(&developer_texturelogging);
3339         Cvar_RegisterVariable(&gl_lightmaps);
3340         Cvar_RegisterVariable(&r_test);
3341         Cvar_RegisterVariable(&r_batch_multidraw);
3342         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
3343         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
3344         Cvar_RegisterVariable(&r_glsl_skeletal);
3345         Cvar_RegisterVariable(&r_glsl_saturation);
3346         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
3347         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
3348         Cvar_RegisterVariable(&r_framedatasize);
3349         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
3350                 Cvar_RegisterVariable(&r_buffermegs[i]);
3351         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
3352         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3353                 Cvar_SetValue("r_fullbrights", 0);
3354 #ifdef DP_MOBILETOUCH
3355         // GLES devices have terrible depth precision in general, so...
3356         Cvar_SetValueQuick(&r_nearclip, 4);
3357         Cvar_SetValueQuick(&r_farclip_base, 4096);
3358         Cvar_SetValueQuick(&r_farclip_world, 0);
3359         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
3360 #endif
3361         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
3362 }
3363
3364 void Render_Init(void)
3365 {
3366         gl_backend_init();
3367         R_Textures_Init();
3368         GL_Main_Init();
3369         Font_Init();
3370         GL_Draw_Init();
3371         R_Shadow_Init();
3372         R_Sky_Init();
3373         GL_Surf_Init();
3374         Sbar_Init();
3375         R_Particles_Init();
3376         R_Explosion_Init();
3377         R_LightningBeams_Init();
3378         Mod_RenderInit();
3379 }
3380
3381 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3382 {
3383         int i;
3384         mplane_t *p;
3385         if (r_trippy.integer)
3386                 return false;
3387         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3388         {
3389                 p = r_refdef.view.frustum + i;
3390                 switch(p->signbits)
3391                 {
3392                 default:
3393                 case 0:
3394                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3395                                 return true;
3396                         break;
3397                 case 1:
3398                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3399                                 return true;
3400                         break;
3401                 case 2:
3402                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3403                                 return true;
3404                         break;
3405                 case 3:
3406                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3407                                 return true;
3408                         break;
3409                 case 4:
3410                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3411                                 return true;
3412                         break;
3413                 case 5:
3414                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3415                                 return true;
3416                         break;
3417                 case 6:
3418                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3419                                 return true;
3420                         break;
3421                 case 7:
3422                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3423                                 return true;
3424                         break;
3425                 }
3426         }
3427         return false;
3428 }
3429
3430 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3431 {
3432         int i;
3433         const mplane_t *p;
3434         if (r_trippy.integer)
3435                 return false;
3436         for (i = 0;i < numplanes;i++)
3437         {
3438                 p = planes + i;
3439                 switch(p->signbits)
3440                 {
3441                 default:
3442                 case 0:
3443                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3444                                 return true;
3445                         break;
3446                 case 1:
3447                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3448                                 return true;
3449                         break;
3450                 case 2:
3451                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3452                                 return true;
3453                         break;
3454                 case 3:
3455                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3456                                 return true;
3457                         break;
3458                 case 4:
3459                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3460                                 return true;
3461                         break;
3462                 case 5:
3463                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3464                                 return true;
3465                         break;
3466                 case 6:
3467                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3468                                 return true;
3469                         break;
3470                 case 7:
3471                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3472                                 return true;
3473                         break;
3474                 }
3475         }
3476         return false;
3477 }
3478
3479 //==================================================================================
3480
3481 // LordHavoc: this stores temporary data used within the same frame
3482
3483 typedef struct r_framedata_mem_s
3484 {
3485         struct r_framedata_mem_s *purge; // older mem block to free on next frame
3486         size_t size; // how much usable space
3487         size_t current; // how much space in use
3488         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
3489         size_t wantedsize; // how much space was allocated
3490         unsigned char *data; // start of real data (16byte aligned)
3491 }
3492 r_framedata_mem_t;
3493
3494 static r_framedata_mem_t *r_framedata_mem;
3495
3496 void R_FrameData_Reset(void)
3497 {
3498         while (r_framedata_mem)
3499         {
3500                 r_framedata_mem_t *next = r_framedata_mem->purge;
3501                 Mem_Free(r_framedata_mem);
3502                 r_framedata_mem = next;
3503         }
3504 }
3505
3506 static void R_FrameData_Resize(qboolean mustgrow)
3507 {
3508         size_t wantedsize;
3509         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3510         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
3511         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
3512         {
3513                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
3514                 newmem->wantedsize = wantedsize;
3515                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
3516                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
3517                 newmem->current = 0;
3518                 newmem->mark = 0;
3519                 newmem->purge = r_framedata_mem;
3520                 r_framedata_mem = newmem;
3521         }
3522 }
3523
3524 void R_FrameData_NewFrame(void)
3525 {
3526         R_FrameData_Resize(false);
3527         if (!r_framedata_mem)
3528                 return;
3529         // if we ran out of space on the last frame, free the old memory now
3530         while (r_framedata_mem->purge)
3531         {
3532                 // repeatedly remove the second item in the list, leaving only head
3533                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
3534                 Mem_Free(r_framedata_mem->purge);
3535                 r_framedata_mem->purge = next;
3536         }
3537         // reset the current mem pointer
3538         r_framedata_mem->current = 0;
3539         r_framedata_mem->mark = 0;
3540 }
3541
3542 void *R_FrameData_Alloc(size_t size)
3543 {
3544         void *data;
3545         float newvalue;
3546
3547         // align to 16 byte boundary - the data pointer is already aligned, so we
3548         // only need to ensure the size of every allocation is also aligned
3549         size = (size + 15) & ~15;
3550
3551         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
3552         {
3553                 // emergency - we ran out of space, allocate more memory
3554                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
3555                 newvalue = r_framedatasize.value * 2.0f;
3556                 // 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
3557                 if (sizeof(size_t) >= 8)
3558                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
3559                 else
3560                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
3561                 // this might not be a growing it, but we'll allocate another buffer every time
3562                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
3563                 R_FrameData_Resize(true);
3564         }
3565
3566         data = r_framedata_mem->data + r_framedata_mem->current;
3567         r_framedata_mem->current += size;
3568
3569         // count the usage for stats
3570         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
3571         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
3572
3573         return (void *)data;
3574 }
3575
3576 void *R_FrameData_Store(size_t size, void *data)
3577 {
3578         void *d = R_FrameData_Alloc(size);
3579         if (d && data)
3580                 memcpy(d, data, size);
3581         return d;
3582 }
3583
3584 void R_FrameData_SetMark(void)
3585 {
3586         if (!r_framedata_mem)
3587                 return;
3588         r_framedata_mem->mark = r_framedata_mem->current;
3589 }
3590
3591 void R_FrameData_ReturnToMark(void)
3592 {
3593         if (!r_framedata_mem)
3594                 return;
3595         r_framedata_mem->current = r_framedata_mem->mark;
3596 }
3597
3598 //==================================================================================
3599
3600 // avoid reusing the same buffer objects on consecutive frames
3601 #define R_BUFFERDATA_CYCLE 3
3602
3603 typedef struct r_bufferdata_buffer_s
3604 {
3605         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
3606         size_t size; // how much usable space
3607         size_t current; // how much space in use
3608         r_meshbuffer_t *buffer; // the buffer itself
3609 }
3610 r_bufferdata_buffer_t;
3611
3612 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
3613 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
3614
3615 /// frees all dynamic buffers
3616 void R_BufferData_Reset(void)
3617 {
3618         int cycle, type;
3619         r_bufferdata_buffer_t **p, *mem;
3620         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
3621         {
3622                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3623                 {
3624                         // free all buffers
3625                         p = &r_bufferdata_buffer[cycle][type];
3626                         while (*p)
3627                         {
3628                                 mem = *p;
3629                                 *p = (*p)->purge;
3630                                 if (mem->buffer)
3631                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3632                                 Mem_Free(mem);
3633                         }
3634                 }
3635         }
3636 }
3637
3638 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
3639 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
3640 {
3641         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3642         size_t size;
3643         float newvalue = r_buffermegs[type].value;
3644
3645         // increase the cvar if we have to (but only if we already have a mem)
3646         if (mustgrow && mem)
3647                 newvalue *= 2.0f;
3648         newvalue = bound(0.25f, newvalue, 256.0f);
3649         while (newvalue * 1024*1024 < minsize)
3650                 newvalue *= 2.0f;
3651
3652         // clamp the cvar to valid range
3653         newvalue = bound(0.25f, newvalue, 256.0f);
3654         if (r_buffermegs[type].value != newvalue)
3655                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
3656
3657         // calculate size in bytes
3658         size = (size_t)(newvalue * 1024*1024);
3659         size = bound(131072, size, 256*1024*1024);
3660
3661         // allocate a new buffer if the size is different (purge old one later)
3662         // or if we were told we must grow the buffer
3663         if (!mem || mem->size != size || mustgrow)
3664         {
3665                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
3666                 mem->size = size;
3667                 mem->current = 0;
3668                 if (type == R_BUFFERDATA_VERTEX)
3669                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
3670                 else if (type == R_BUFFERDATA_INDEX16)
3671                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
3672                 else if (type == R_BUFFERDATA_INDEX32)
3673                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
3674                 else if (type == R_BUFFERDATA_UNIFORM)
3675                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
3676                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
3677                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
3678         }
3679 }
3680
3681 void R_BufferData_NewFrame(void)
3682 {
3683         int type;
3684         r_bufferdata_buffer_t **p, *mem;
3685         // cycle to the next frame's buffers
3686         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
3687         // if we ran out of space on the last time we used these buffers, free the old memory now
3688         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
3689         {
3690                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
3691                 {
3692                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
3693                         // free all but the head buffer, this is how we recycle obsolete
3694                         // buffers after they are no longer in use
3695                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
3696                         while (*p)
3697                         {
3698                                 mem = *p;
3699                                 *p = (*p)->purge;
3700                                 if (mem->buffer)
3701                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
3702                                 Mem_Free(mem);
3703                         }
3704                         // reset the current offset
3705                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
3706                 }
3707         }
3708 }
3709
3710 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
3711 {
3712         r_bufferdata_buffer_t *mem;
3713         int offset = 0;
3714         int padsize;
3715
3716         *returnbufferoffset = 0;
3717
3718         // align size to a byte boundary appropriate for the buffer type, this
3719         // makes all allocations have aligned start offsets
3720         if (type == R_BUFFERDATA_UNIFORM)
3721                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
3722         else
3723                 padsize = (datasize + 15) & ~15;
3724
3725         // if we ran out of space in this buffer we must allocate a new one
3726         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)
3727                 R_BufferData_Resize(type, true, padsize);
3728
3729         // if the resize did not give us enough memory, fail
3730         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)
3731                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
3732
3733         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
3734         offset = (int)mem->current;
3735         mem->current += padsize;
3736
3737         // upload the data to the buffer at the chosen offset
3738         if (offset == 0)
3739                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
3740         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
3741
3742         // count the usage for stats
3743         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
3744         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
3745
3746         // return the buffer offset
3747         *returnbufferoffset = offset;
3748
3749         return mem->buffer;
3750 }
3751
3752 //==================================================================================
3753
3754 // LordHavoc: animcache originally written by Echon, rewritten since then
3755
3756 /**
3757  * Animation cache prevents re-generating mesh data for an animated model
3758  * multiple times in one frame for lighting, shadowing, reflections, etc.
3759  */
3760
3761 void R_AnimCache_Free(void)
3762 {
3763 }
3764
3765 void R_AnimCache_ClearCache(void)
3766 {
3767         int i;
3768         entity_render_t *ent;
3769
3770         for (i = 0;i < r_refdef.scene.numentities;i++)
3771         {
3772                 ent = r_refdef.scene.entities[i];
3773                 ent->animcache_vertex3f = NULL;
3774                 ent->animcache_vertex3f_vertexbuffer = NULL;
3775                 ent->animcache_vertex3f_bufferoffset = 0;
3776                 ent->animcache_normal3f = NULL;
3777                 ent->animcache_normal3f_vertexbuffer = NULL;
3778                 ent->animcache_normal3f_bufferoffset = 0;
3779                 ent->animcache_svector3f = NULL;
3780                 ent->animcache_svector3f_vertexbuffer = NULL;
3781                 ent->animcache_svector3f_bufferoffset = 0;
3782                 ent->animcache_tvector3f = NULL;
3783                 ent->animcache_tvector3f_vertexbuffer = NULL;
3784                 ent->animcache_tvector3f_bufferoffset = 0;
3785                 ent->animcache_skeletaltransform3x4 = NULL;
3786                 ent->animcache_skeletaltransform3x4buffer = NULL;
3787                 ent->animcache_skeletaltransform3x4offset = 0;
3788                 ent->animcache_skeletaltransform3x4size = 0;
3789         }
3790 }
3791
3792 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3793 {
3794         dp_model_t *model = ent->model;
3795         int numvertices;
3796
3797         // see if this ent is worth caching
3798         if (!model || !model->Draw || !model->AnimateVertices)
3799                 return false;
3800         // nothing to cache if it contains no animations and has no skeleton
3801         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
3802                 return false;
3803         // see if it is already cached for gpuskeletal
3804         if (ent->animcache_skeletaltransform3x4)
3805                 return false;
3806         // see if it is already cached as a mesh
3807         if (ent->animcache_vertex3f)
3808         {
3809                 // check if we need to add normals or tangents
3810                 if (ent->animcache_normal3f)
3811                         wantnormals = false;
3812                 if (ent->animcache_svector3f)
3813                         wanttangents = false;
3814                 if (!wantnormals && !wanttangents)
3815                         return false;
3816         }
3817
3818         // check which kind of cache we need to generate
3819         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
3820         {
3821                 // cache the skeleton so the vertex shader can use it
3822                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
3823                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
3824                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
3825                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
3826                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
3827                 // note: this can fail if the buffer is at the grow limit
3828                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
3829                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
3830         }
3831         else if (ent->animcache_vertex3f)
3832         {
3833                 // mesh was already cached but we may need to add normals/tangents
3834                 // (this only happens with multiple views, reflections, cameras, etc)
3835                 if (wantnormals || wanttangents)
3836                 {
3837                         numvertices = model->surfmesh.num_vertices;
3838                         if (wantnormals)
3839                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3840                         if (wanttangents)
3841                         {
3842                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3843                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3844                         }
3845                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3846                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3847                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3848                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3849                 }
3850         }
3851         else
3852         {
3853                 // generate mesh cache
3854                 numvertices = model->surfmesh.num_vertices;
3855                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3856                 if (wantnormals)
3857                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3858                 if (wanttangents)
3859                 {
3860                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3861                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
3862                 }
3863                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3864                 if (wantnormals || wanttangents)
3865                 {
3866                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
3867                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
3868                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
3869                 }
3870                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
3871                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
3872                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
3873         }
3874         return true;
3875 }
3876
3877 void R_AnimCache_CacheVisibleEntities(void)
3878 {
3879         int i;
3880
3881         // TODO: thread this
3882         // NOTE: R_PrepareRTLights() also caches entities
3883
3884         for (i = 0;i < r_refdef.scene.numentities;i++)
3885                 if (r_refdef.viewcache.entityvisible[i])
3886                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], true, true);
3887 }
3888
3889 //==================================================================================
3890
3891 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)
3892 {
3893         int i;
3894         vec3_t eyemins, eyemaxs;
3895         vec3_t boxmins, boxmaxs;
3896         vec3_t padmins, padmaxs;
3897         vec3_t start;
3898         vec3_t end;
3899         dp_model_t *model = r_refdef.scene.worldmodel;
3900         static vec3_t positions[] = {
3901                 { 0.5f, 0.5f, 0.5f },
3902                 { 0.0f, 0.0f, 0.0f },
3903                 { 0.0f, 0.0f, 1.0f },
3904                 { 0.0f, 1.0f, 0.0f },
3905                 { 0.0f, 1.0f, 1.0f },
3906                 { 1.0f, 0.0f, 0.0f },
3907                 { 1.0f, 0.0f, 1.0f },
3908                 { 1.0f, 1.0f, 0.0f },
3909                 { 1.0f, 1.0f, 1.0f },
3910         };
3911
3912         // sample count can be set to -1 to skip this logic, for flicker-prone objects
3913         if (numsamples < 0)
3914                 return true;
3915
3916         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
3917         if (!r_refdef.view.usevieworiginculling)
3918                 return true;
3919
3920         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
3921                 return true;
3922
3923         // expand the eye box a little
3924         eyemins[0] = eye[0] - eyejitter;
3925         eyemaxs[0] = eye[0] + eyejitter;
3926         eyemins[1] = eye[1] - eyejitter;
3927         eyemaxs[1] = eye[1] + eyejitter;
3928         eyemins[2] = eye[2] - eyejitter;
3929         eyemaxs[2] = eye[2] + eyejitter;
3930         // expand the box a little
3931         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
3932         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
3933         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
3934         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
3935         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
3936         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
3937         // make an even larger box for the acceptable area
3938         padmins[0] = boxmins[0] - pad;
3939         padmaxs[0] = boxmaxs[0] + pad;
3940         padmins[1] = boxmins[1] - pad;
3941         padmaxs[1] = boxmaxs[1] + pad;
3942         padmins[2] = boxmins[2] - pad;
3943         padmaxs[2] = boxmaxs[2] + pad;
3944
3945         // return true if eye overlaps enlarged box
3946         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
3947                 return true;
3948
3949         // try specific positions in the box first - note that these can be cached
3950         if (r_cullentities_trace_entityocclusion.integer)
3951         {
3952                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
3953                 {
3954                         VectorCopy(eye, start);
3955                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
3956                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
3957                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
3958                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
3959                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
3960                         // not picky - if the trace ended anywhere in the box we're good
3961                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
3962                                 return true;
3963                 }
3964         }
3965         else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
3966                 return true;
3967
3968         // try various random positions
3969         for (i = 0; i < numsamples; i++)
3970         {
3971                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
3972                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3973                 if (r_cullentities_trace_entityocclusion.integer)
3974                 {
3975                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
3976                         // not picky - if the trace ended anywhere in the box we're good
3977                         if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
3978                                 return true;
3979                 }
3980                 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
3981                         return true;
3982         }
3983
3984         return false;
3985 }
3986
3987
3988 static void R_View_UpdateEntityVisible (void)
3989 {
3990         int i;
3991         int renderimask;
3992         int samples;
3993         entity_render_t *ent;
3994
3995         if (r_refdef.envmap || r_fb.water.hideplayer)
3996                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
3997         else if (chase_active.integer || r_fb.water.renderingscene)
3998                 renderimask = RENDER_VIEWMODEL;
3999         else
4000                 renderimask = RENDER_EXTERIORMODEL;
4001         if (!r_drawviewmodel.integer)
4002                 renderimask |= RENDER_VIEWMODEL;
4003         if (!r_drawexteriormodel.integer)
4004                 renderimask |= RENDER_EXTERIORMODEL;
4005         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4006         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4007         {
4008                 // worldmodel can check visibility
4009                 for (i = 0;i < r_refdef.scene.numentities;i++)
4010                 {
4011                         ent = r_refdef.scene.entities[i];
4012                         if (!(ent->flags & renderimask))
4013                         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)))
4014                         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))
4015                                 r_refdef.viewcache.entityvisible[i] = true;
4016                 }
4017         }
4018         else
4019         {
4020                 // no worldmodel or it can't check visibility
4021                 for (i = 0;i < r_refdef.scene.numentities;i++)
4022                 {
4023                         ent = r_refdef.scene.entities[i];
4024                         if (!(ent->flags & renderimask))
4025                         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)))
4026                                 r_refdef.viewcache.entityvisible[i] = true;
4027                 }
4028         }
4029         if (r_cullentities_trace.integer)
4030         {
4031                 for (i = 0;i < r_refdef.scene.numentities;i++)
4032                 {
4033                         if (!r_refdef.viewcache.entityvisible[i])
4034                                 continue;
4035                         ent = r_refdef.scene.entities[i];
4036                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4037                         {
4038                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
4039                                 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))
4040                                         ent->last_trace_visibility = realtime;
4041                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4042                                         r_refdef.viewcache.entityvisible[i] = 0;
4043                         }
4044                 }
4045         }
4046 }
4047
4048 /// only used if skyrendermasked, and normally returns false
4049 static int R_DrawBrushModelsSky (void)
4050 {
4051         int i, sky;
4052         entity_render_t *ent;
4053
4054         sky = false;
4055         for (i = 0;i < r_refdef.scene.numentities;i++)
4056         {
4057                 if (!r_refdef.viewcache.entityvisible[i])
4058                         continue;
4059                 ent = r_refdef.scene.entities[i];
4060                 if (!ent->model || !ent->model->DrawSky)
4061                         continue;
4062                 ent->model->DrawSky(ent);
4063                 sky = true;
4064         }
4065         return sky;
4066 }
4067
4068 static void R_DrawNoModel(entity_render_t *ent);
4069 static void R_DrawModels(void)
4070 {
4071         int i;
4072         entity_render_t *ent;
4073
4074         for (i = 0;i < r_refdef.scene.numentities;i++)
4075         {
4076                 if (!r_refdef.viewcache.entityvisible[i])
4077                         continue;
4078                 ent = r_refdef.scene.entities[i];
4079                 r_refdef.stats[r_stat_entities]++;
4080                 /*
4081                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4082                 {
4083                         vec3_t f, l, u, o;
4084                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4085                         Con_Printf("R_DrawModels\n");
4086                         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]);
4087                         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);
4088                         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);
4089                 }
4090                 */
4091                 if (ent->model && ent->model->Draw != NULL)
4092                         ent->model->Draw(ent);
4093                 else
4094                         R_DrawNoModel(ent);
4095         }
4096 }
4097
4098 static void R_DrawModelsDepth(void)
4099 {
4100         int i;
4101         entity_render_t *ent;
4102
4103         for (i = 0;i < r_refdef.scene.numentities;i++)
4104         {
4105                 if (!r_refdef.viewcache.entityvisible[i])
4106                         continue;
4107                 ent = r_refdef.scene.entities[i];
4108                 if (ent->model && ent->model->DrawDepth != NULL)
4109                         ent->model->DrawDepth(ent);
4110         }
4111 }
4112
4113 static void R_DrawModelsDebug(void)
4114 {
4115         int i;
4116         entity_render_t *ent;
4117
4118         for (i = 0;i < r_refdef.scene.numentities;i++)
4119         {
4120                 if (!r_refdef.viewcache.entityvisible[i])
4121                         continue;
4122                 ent = r_refdef.scene.entities[i];
4123                 if (ent->model && ent->model->DrawDebug != NULL)
4124                         ent->model->DrawDebug(ent);
4125         }
4126 }
4127
4128 static void R_DrawModelsAddWaterPlanes(void)
4129 {
4130         int i;
4131         entity_render_t *ent;
4132
4133         for (i = 0;i < r_refdef.scene.numentities;i++)
4134         {
4135                 if (!r_refdef.viewcache.entityvisible[i])
4136                         continue;
4137                 ent = r_refdef.scene.entities[i];
4138                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4139                         ent->model->DrawAddWaterPlanes(ent);
4140         }
4141 }
4142
4143 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}};
4144
4145 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4146 {
4147         if (r_hdr_irisadaptation.integer)
4148         {
4149                 vec3_t p;
4150                 vec3_t ambient;
4151                 vec3_t diffuse;
4152                 vec3_t diffusenormal;
4153                 vec3_t forward;
4154                 vec_t brightness = 0.0f;
4155                 vec_t goal;
4156                 vec_t current;
4157                 vec_t d;
4158                 int c;
4159                 VectorCopy(r_refdef.view.forward, forward);
4160                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
4161                 {
4162                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
4163                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
4164                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
4165                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
4166                         d = DotProduct(forward, diffusenormal);
4167                         brightness += VectorLength(ambient);
4168                         if (d > 0)
4169                                 brightness += d * VectorLength(diffuse);
4170                 }
4171                 brightness *= 1.0f / c;
4172                 brightness += 0.00001f; // make sure it's never zero
4173                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4174                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4175                 current = r_hdr_irisadaptation_value.value;
4176                 if (current < goal)
4177                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
4178                 else if (current > goal)
4179                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
4180                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4181                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4182         }
4183         else if (r_hdr_irisadaptation_value.value != 1.0f)
4184                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4185 }
4186
4187 static void R_View_SetFrustum(const int *scissor)
4188 {
4189         int i;
4190         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4191         vec3_t forward, left, up, origin, v;
4192
4193         if(scissor)
4194         {
4195                 // flipped x coordinates (because x points left here)
4196                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4197                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4198                 // non-flipped y coordinates
4199                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4200                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4201         }
4202
4203         // we can't trust r_refdef.view.forward and friends in reflected scenes
4204         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4205
4206 #if 0
4207         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4208         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4209         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4210         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4211         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4212         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4213         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4214         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4215         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4216         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4217         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4218         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4219 #endif
4220
4221 #if 0
4222         zNear = r_refdef.nearclip;
4223         nudge = 1.0 - 1.0 / (1<<23);
4224         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4225         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4226         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4227         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4228         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4229         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4230         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4231         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4232 #endif
4233
4234
4235
4236 #if 0
4237         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4238         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4239         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4240         r_refdef.view.frustum[0].dist = m[15] - m[12];
4241
4242         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4243         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4244         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4245         r_refdef.view.frustum[1].dist = m[15] + m[12];
4246
4247         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4248         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4249         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4250         r_refdef.view.frustum[2].dist = m[15] - m[13];
4251
4252         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4253         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4254         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4255         r_refdef.view.frustum[3].dist = m[15] + m[13];
4256
4257         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4258         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4259         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4260         r_refdef.view.frustum[4].dist = m[15] - m[14];
4261
4262         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4263         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4264         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4265         r_refdef.view.frustum[5].dist = m[15] + m[14];
4266 #endif
4267
4268         if (r_refdef.view.useperspective)
4269         {
4270                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4271                 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]);
4272                 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]);
4273                 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]);
4274                 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]);
4275
4276                 // then the normals from the corners relative to origin
4277                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4278                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4279                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4280                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4281
4282                 // in a NORMAL view, forward cross left == up
4283                 // in a REFLECTED view, forward cross left == down
4284                 // so our cross products above need to be adjusted for a left handed coordinate system
4285                 CrossProduct(forward, left, v);
4286                 if(DotProduct(v, up) < 0)
4287                 {
4288                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4289                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4290                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4291                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4292                 }
4293
4294                 // Leaving those out was a mistake, those were in the old code, and they
4295                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4296                 // I couldn't reproduce it after adding those normalizations. --blub
4297                 VectorNormalize(r_refdef.view.frustum[0].normal);
4298                 VectorNormalize(r_refdef.view.frustum[1].normal);
4299                 VectorNormalize(r_refdef.view.frustum[2].normal);
4300                 VectorNormalize(r_refdef.view.frustum[3].normal);
4301
4302                 // make the corners absolute
4303                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4304                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4305                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4306                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4307
4308                 // one more normal
4309                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4310
4311                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4312                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4313                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4314                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4315                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4316         }
4317         else
4318         {
4319                 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
4320                 VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
4321                 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
4322                 VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
4323                 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
4324                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
4325                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
4326                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
4327                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
4328                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
4329         }
4330         r_refdef.view.numfrustumplanes = 5;
4331
4332         if (r_refdef.view.useclipplane)
4333         {
4334                 r_refdef.view.numfrustumplanes = 6;
4335                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4336         }
4337
4338         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4339                 PlaneClassify(r_refdef.view.frustum + i);
4340
4341         // LordHavoc: note to all quake engine coders, Quake had a special case
4342         // for 90 degrees which assumed a square view (wrong), so I removed it,
4343         // Quake2 has it disabled as well.
4344
4345         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4346         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4347         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4348         //PlaneClassify(&frustum[0]);
4349
4350         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4351         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4352         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4353         //PlaneClassify(&frustum[1]);
4354
4355         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4356         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4357         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4358         //PlaneClassify(&frustum[2]);
4359
4360         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4361         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4362         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4363         //PlaneClassify(&frustum[3]);
4364
4365         // nearclip plane
4366         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4367         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4368         //PlaneClassify(&frustum[4]);
4369 }
4370
4371 static void R_View_UpdateWithScissor(const int *myscissor)
4372 {
4373         R_Main_ResizeViewCache();
4374         R_View_SetFrustum(myscissor);
4375         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4376         R_View_UpdateEntityVisible();
4377 }
4378
4379 static void R_View_Update(void)
4380 {
4381         R_Main_ResizeViewCache();
4382         R_View_SetFrustum(NULL);
4383         R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
4384         R_View_UpdateEntityVisible();
4385 }
4386
4387 float viewscalefpsadjusted = 1.0f;
4388
4389 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
4390 {
4391         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
4392         scale = bound(0.03125f, scale, 1.0f);
4393         *outwidth = (int)ceil(width * scale);
4394         *outheight = (int)ceil(height * scale);
4395 }
4396
4397 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4398 {
4399         const float *customclipplane = NULL;
4400         float plane[4];
4401         int /*rtwidth,*/ rtheight;
4402         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4403         {
4404                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
4405                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4406                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4407                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4408                         dist = r_refdef.view.clipplane.dist;
4409                 plane[0] = r_refdef.view.clipplane.normal[0];
4410                 plane[1] = r_refdef.view.clipplane.normal[1];
4411                 plane[2] = r_refdef.view.clipplane.normal[2];
4412                 plane[3] = -dist;
4413                 customclipplane = plane;
4414         }
4415
4416         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
4417         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
4418
4419         if (!r_refdef.view.useperspective)
4420                 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);
4421         else if (vid.stencil && r_useinfinitefarclip.integer)
4422                 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);
4423         else
4424                 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);
4425         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4426         R_SetViewport(&r_refdef.view.viewport);
4427 }
4428
4429 void R_EntityMatrix(const matrix4x4_t *matrix)
4430 {
4431         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4432         {
4433                 gl_modelmatrixchanged = false;
4434                 gl_modelmatrix = *matrix;
4435                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4436                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4437                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4438                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4439                 CHECKGLERROR
4440                 switch(vid.renderpath)
4441                 {
4442                 case RENDERPATH_GL32:
4443                 case RENDERPATH_GLES2:
4444                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4445                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4446                         break;
4447                 }
4448         }
4449 }
4450
4451 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
4452 {
4453         r_viewport_t viewport;
4454
4455         CHECKGLERROR
4456
4457         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4458         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
4459         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
4460         R_SetViewport(&viewport);
4461         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4462         GL_Color(1, 1, 1, 1);
4463         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4464         GL_BlendFunc(GL_ONE, GL_ZERO);
4465         GL_ScissorTest(false);
4466         GL_DepthMask(false);
4467         GL_DepthRange(0, 1);
4468         GL_DepthTest(false);
4469         GL_DepthFunc(GL_LEQUAL);
4470         R_EntityMatrix(&identitymatrix);
4471         R_Mesh_ResetTextureState();
4472         GL_PolygonOffset(0, 0);
4473         switch(vid.renderpath)
4474         {
4475         case RENDERPATH_GL32:
4476         case RENDERPATH_GLES2:
4477                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4478                 break;
4479         }
4480         GL_CullFace(GL_NONE);
4481
4482         CHECKGLERROR
4483 }
4484
4485 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4486 {
4487         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
4488 }
4489
4490 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
4491 {
4492         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
4493         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4494         GL_Color(1, 1, 1, 1);
4495         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4496         GL_BlendFunc(GL_ONE, GL_ZERO);
4497         GL_ScissorTest(true);
4498         GL_DepthMask(true);
4499         GL_DepthRange(0, 1);
4500         GL_DepthTest(true);
4501         GL_DepthFunc(GL_LEQUAL);
4502         R_EntityMatrix(&identitymatrix);
4503         R_Mesh_ResetTextureState();
4504         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4505         switch(vid.renderpath)
4506         {
4507         case RENDERPATH_GL32:
4508         case RENDERPATH_GLES2:
4509                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4510                 break;
4511         }
4512         GL_CullFace(r_refdef.view.cullface_back);
4513 }
4514
4515 /*
4516 ================
4517 R_RenderView_UpdateViewVectors
4518 ================
4519 */
4520 void R_RenderView_UpdateViewVectors(void)
4521 {
4522         // break apart the view matrix into vectors for various purposes
4523         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4524         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4525         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4526         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4527         // make an inverted copy of the view matrix for tracking sprites
4528         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4529 }
4530
4531 void R_RenderTarget_FreeUnused(qboolean force)
4532 {
4533         int i, j, end;
4534         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4535         for (i = 0; i < end; i++)
4536         {
4537                 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4538                 // free resources for rendertargets that have not been used for a while
4539                 // (note: this check is run after the frame render, so any targets used
4540                 // this frame will not be affected even at low framerates)
4541                 if (r && (realtime - r->lastusetime > 0.2 || force))
4542                 {
4543                         if (r->fbo)
4544                                 R_Mesh_DestroyFramebufferObject(r->fbo);
4545                         for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
4546                                 if (r->colortexture[j])
4547                                         R_FreeTexture(r->colortexture[j]);
4548                         if (r->depthtexture)
4549                                 R_FreeTexture(r->depthtexture);
4550                         Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
4551                 }
4552         }
4553 }
4554
4555 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
4556 {
4557         float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
4558         x1 = x * iw;
4559         x2 = (x + w) * iw;
4560         y1 = (th - y) * ih;
4561         y2 = (th - y - h) * ih;
4562         texcoord2f[0] = x1;
4563         texcoord2f[2] = x2;
4564         texcoord2f[4] = x2;
4565         texcoord2f[6] = x1;
4566         texcoord2f[1] = y1;
4567         texcoord2f[3] = y1;
4568         texcoord2f[5] = y2;
4569         texcoord2f[7] = y2;
4570 }
4571
4572 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)
4573 {
4574         int i, j, end;
4575         r_rendertarget_t *r = NULL;
4576         char vabuf[256];
4577         // first try to reuse an existing slot if possible
4578         end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
4579         for (i = 0; i < end; i++)
4580         {
4581                 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
4582                 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)
4583                         break;
4584         }
4585         if (i == end)
4586         {
4587                 // no unused exact match found, so we have to make one in the first unused slot
4588                 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
4589                 r->texturewidth = texturewidth;
4590                 r->textureheight = textureheight;
4591                 r->colortextype[0] = colortextype0;
4592                 r->colortextype[1] = colortextype1;
4593                 r->colortextype[2] = colortextype2;
4594                 r->colortextype[3] = colortextype3;
4595                 r->depthtextype = depthtextype;
4596                 r->depthisrenderbuffer = depthisrenderbuffer;
4597                 for (j = 0; j < 4; j++)
4598                         if (r->colortextype[j])
4599                                 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);
4600                 if (r->depthtextype)
4601                 {
4602                         if (r->depthisrenderbuffer)
4603                                 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);
4604                         else
4605                                 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);
4606                 }
4607                 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
4608         }
4609         r_refdef.stats[r_stat_rendertargets_used]++;
4610         r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
4611         r->lastusetime = realtime;
4612         R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
4613         return r;
4614 }
4615
4616 static void R_Water_StartFrame(void)
4617 {
4618         int waterwidth, waterheight;
4619
4620         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4621                 return;
4622
4623         // set waterwidth and waterheight to the water resolution that will be
4624         // used (often less than the screen resolution for faster rendering)
4625         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4626         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4627         R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
4628
4629         if (!r_water.integer || r_showsurfaces.integer)
4630                 waterwidth = waterheight = 0;
4631
4632         // set up variables that will be used in shader setup
4633         r_fb.water.waterwidth = waterwidth;
4634         r_fb.water.waterheight = waterheight;
4635         r_fb.water.texturewidth = waterwidth;
4636         r_fb.water.textureheight = waterheight;
4637         r_fb.water.camerawidth = waterwidth;
4638         r_fb.water.cameraheight = waterheight;
4639         r_fb.water.screenscale[0] = 0.5f;
4640         r_fb.water.screenscale[1] = 0.5f;
4641         r_fb.water.screencenter[0] = 0.5f;
4642         r_fb.water.screencenter[1] = 0.5f;
4643         r_fb.water.enabled = waterwidth != 0;
4644
4645         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
4646         r_fb.water.numwaterplanes = 0;
4647 }
4648
4649 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
4650 {
4651         int planeindex, bestplaneindex, vertexindex;
4652         vec3_t mins, maxs, normal, center, v, n;
4653         vec_t planescore, bestplanescore;
4654         mplane_t plane;
4655         r_waterstate_waterplane_t *p;
4656         texture_t *t = R_GetCurrentTexture(surface->texture);
4657
4658         rsurface.texture = t;
4659         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
4660         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
4661         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
4662                 return;
4663         // average the vertex normals, find the surface bounds (after deformvertexes)
4664         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
4665         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
4666         VectorCopy(n, normal);
4667         VectorCopy(v, mins);
4668         VectorCopy(v, maxs);
4669         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
4670         {
4671                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
4672                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
4673                 VectorAdd(normal, n, normal);
4674                 mins[0] = min(mins[0], v[0]);
4675                 mins[1] = min(mins[1], v[1]);
4676                 mins[2] = min(mins[2], v[2]);
4677                 maxs[0] = max(maxs[0], v[0]);
4678                 maxs[1] = max(maxs[1], v[1]);
4679                 maxs[2] = max(maxs[2], v[2]);
4680         }
4681         VectorNormalize(normal);
4682         VectorMAM(0.5f, mins, 0.5f, maxs, center);
4683
4684         VectorCopy(normal, plane.normal);
4685         VectorNormalize(plane.normal);
4686         plane.dist = DotProduct(center, plane.normal);
4687         PlaneClassify(&plane);
4688         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4689         {
4690                 // skip backfaces (except if nocullface is set)
4691 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4692 //                      return;
4693                 VectorNegate(plane.normal, plane.normal);
4694                 plane.dist *= -1;
4695                 PlaneClassify(&plane);
4696         }
4697
4698
4699         // find a matching plane if there is one
4700         bestplaneindex = -1;
4701         bestplanescore = 1048576.0f;
4702         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4703         {
4704                 if(p->camera_entity == t->camera_entity)
4705                 {
4706                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
4707                         if (bestplaneindex < 0 || bestplanescore > planescore)
4708                         {
4709                                 bestplaneindex = planeindex;
4710                                 bestplanescore = planescore;
4711                         }
4712                 }
4713         }
4714         planeindex = bestplaneindex;
4715
4716         // if this surface does not fit any known plane rendered this frame, add one
4717         if (planeindex < 0 || bestplanescore > 0.001f)
4718         {
4719                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
4720                 {
4721                         // store the new plane
4722                         planeindex = r_fb.water.numwaterplanes++;
4723                         p = r_fb.water.waterplanes + planeindex;
4724                         p->plane = plane;
4725                         // clear materialflags and pvs
4726                         p->materialflags = 0;
4727                         p->pvsvalid = false;
4728                         p->camera_entity = t->camera_entity;
4729                         VectorCopy(mins, p->mins);
4730                         VectorCopy(maxs, p->maxs);
4731                 }
4732                 else
4733                 {
4734                         // We're totally screwed.
4735                         return;
4736                 }
4737         }
4738         else
4739         {
4740                 // merge mins/maxs when we're adding this surface to the plane
4741                 p = r_fb.water.waterplanes + planeindex;
4742                 p->mins[0] = min(p->mins[0], mins[0]);
4743                 p->mins[1] = min(p->mins[1], mins[1]);
4744                 p->mins[2] = min(p->mins[2], mins[2]);
4745                 p->maxs[0] = max(p->maxs[0], maxs[0]);
4746                 p->maxs[1] = max(p->maxs[1], maxs[1]);
4747                 p->maxs[2] = max(p->maxs[2], maxs[2]);
4748         }
4749         // merge this surface's materialflags into the waterplane
4750         p->materialflags |= t->currentmaterialflags;
4751         if(!(p->materialflags & MATERIALFLAG_CAMERA))
4752         {
4753                 // merge this surface's PVS into the waterplane
4754                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4755                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4756                 {
4757                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4758                         p->pvsvalid = true;
4759                 }
4760         }
4761 }
4762
4763 extern cvar_t r_drawparticles;
4764 extern cvar_t r_drawdecals;
4765
4766 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
4767 {
4768         int myscissor[4];
4769         r_refdef_view_t originalview;
4770         r_refdef_view_t myview;
4771         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;
4772         r_waterstate_waterplane_t *p;
4773         vec3_t visorigin;
4774         r_rendertarget_t *rt;
4775
4776         originalview = r_refdef.view;
4777
4778         // lowquality hack, temporarily shut down some cvars and restore afterwards
4779         qualityreduction = r_water_lowquality.integer;
4780         if (qualityreduction > 0)
4781         {
4782                 if (qualityreduction >= 1)
4783                 {
4784                         old_r_shadows = r_shadows.integer;
4785                         old_r_worldrtlight = r_shadow_realtime_world.integer;
4786                         old_r_dlight = r_shadow_realtime_dlight.integer;
4787                         Cvar_SetValueQuick(&r_shadows, 0);
4788                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
4789                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
4790                 }
4791                 if (qualityreduction >= 2)
4792                 {
4793                         old_r_dynamic = r_dynamic.integer;
4794                         old_r_particles = r_drawparticles.integer;
4795                         old_r_decals = r_drawdecals.integer;
4796                         Cvar_SetValueQuick(&r_dynamic, 0);
4797                         Cvar_SetValueQuick(&r_drawparticles, 0);
4798                         Cvar_SetValueQuick(&r_drawdecals, 0);
4799                 }
4800         }
4801
4802         for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
4803         {
4804                 p->rt_reflection = NULL;
4805                 p->rt_refraction = NULL;
4806                 p->rt_camera = NULL;
4807         }
4808
4809         // render views
4810         r_refdef.view = originalview;
4811         r_refdef.view.showdebug = false;
4812         r_refdef.view.width = r_fb.water.waterwidth;
4813         r_refdef.view.height = r_fb.water.waterheight;
4814         r_refdef.view.useclipplane = true;
4815         myview = r_refdef.view;
4816         r_fb.water.renderingscene = true;
4817         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
4818         {
4819                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
4820                         continue;
4821
4822                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4823                 {
4824                         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);
4825                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4826                                 goto error;
4827                         r_refdef.view = myview;
4828                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4829                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4830                         if(r_water_scissormode.integer)
4831                         {
4832                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4833                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4834                                 {
4835                                         p->rt_reflection = NULL;
4836                                         p->rt_refraction = NULL;
4837                                         p->rt_camera = NULL;
4838                                         continue;
4839                                 }
4840                         }
4841
4842                         r_refdef.view.clipplane = p->plane;
4843                         // reflected view origin may be in solid, so don't cull with it
4844                         r_refdef.view.usevieworiginculling = false;
4845                         // reverse the cullface settings for this render
4846                         r_refdef.view.cullface_front = GL_FRONT;
4847                         r_refdef.view.cullface_back = GL_BACK;
4848                         // combined pvs (based on what can be seen from each surface center)
4849                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4850                         {
4851                                 r_refdef.view.usecustompvs = true;
4852                                 if (p->pvsvalid)
4853                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4854                                 else
4855                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4856                         }
4857
4858                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
4859                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4860                         GL_ScissorTest(false);
4861                         R_ClearScreen(r_refdef.fogenabled);
4862                         GL_ScissorTest(true);
4863                         if(r_water_scissormode.integer & 2)
4864                                 R_View_UpdateWithScissor(myscissor);
4865                         else
4866                                 R_View_Update();
4867                         R_AnimCache_CacheVisibleEntities();
4868                         if(r_water_scissormode.integer & 1)
4869                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4870                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4871
4872                         r_fb.water.hideplayer = false;
4873                         p->rt_reflection = rt;
4874                 }
4875
4876                 // render the normal view scene and copy into texture
4877                 // (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)
4878                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4879                 {
4880                         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);
4881                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4882                                 goto error;
4883                         r_refdef.view = myview;
4884                         if(r_water_scissormode.integer)
4885                         {
4886                                 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
4887                                 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
4888                                 {
4889                                         p->rt_reflection = NULL;
4890                                         p->rt_refraction = NULL;
4891                                         p->rt_camera = NULL;
4892                                         continue;
4893                                 }
4894                         }
4895
4896                         // combined pvs (based on what can be seen from each surface center)
4897                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4898                         {
4899                                 r_refdef.view.usecustompvs = true;
4900                                 if (p->pvsvalid)
4901                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4902                                 else
4903                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4904                         }
4905
4906                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
4907
4908                         r_refdef.view.clipplane = p->plane;
4909                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4910                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4911
4912                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
4913                         {
4914                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
4915                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
4916                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
4917                                 R_RenderView_UpdateViewVectors();
4918                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
4919                                 {
4920                                         r_refdef.view.usecustompvs = true;
4921                                         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);
4922                                 }
4923                         }
4924
4925                         PlaneClassify(&r_refdef.view.clipplane);
4926
4927                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4928                         GL_ScissorTest(false);
4929                         R_ClearScreen(r_refdef.fogenabled);
4930                         GL_ScissorTest(true);
4931                         if(r_water_scissormode.integer & 2)
4932                                 R_View_UpdateWithScissor(myscissor);
4933                         else
4934                                 R_View_Update();
4935                         R_AnimCache_CacheVisibleEntities();
4936                         if(r_water_scissormode.integer & 1)
4937                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
4938                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4939
4940                         r_fb.water.hideplayer = false;
4941                         p->rt_refraction = rt;
4942                 }
4943                 else if (p->materialflags & MATERIALFLAG_CAMERA)
4944                 {
4945                         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);
4946                         if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
4947                                 goto error;
4948                         r_refdef.view = myview;
4949
4950                         r_refdef.view.clipplane = p->plane;
4951                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4952                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4953
4954                         r_refdef.view.width = r_fb.water.camerawidth;
4955                         r_refdef.view.height = r_fb.water.cameraheight;
4956                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
4957                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
4958                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
4959                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
4960
4961                         if(p->camera_entity)
4962                         {
4963                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
4964                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
4965                         }
4966
4967                         // note: all of the view is used for displaying... so
4968                         // there is no use in scissoring
4969
4970                         // reverse the cullface settings for this render
4971                         r_refdef.view.cullface_front = GL_FRONT;
4972                         r_refdef.view.cullface_back = GL_BACK;
4973                         // also reverse the view matrix
4974                         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
4975                         R_RenderView_UpdateViewVectors();
4976                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
4977                         {
4978                                 r_refdef.view.usecustompvs = true;
4979                                 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);
4980                         }
4981                         
4982                         // camera needs no clipplane
4983                         r_refdef.view.useclipplane = false;
4984                         // TODO: is the camera origin always valid?  if so we don't need to clear this
4985                         r_refdef.view.usevieworiginculling = false;
4986
4987                         PlaneClassify(&r_refdef.view.clipplane);
4988
4989                         r_fb.water.hideplayer = false;
4990
4991                         R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4992                         GL_ScissorTest(false);
4993                         R_ClearScreen(r_refdef.fogenabled);
4994                         GL_ScissorTest(true);
4995                         R_View_Update();
4996                         R_AnimCache_CacheVisibleEntities();
4997                         R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
4998
4999                         r_fb.water.hideplayer = false;
5000                         p->rt_camera = rt;
5001                 }
5002
5003         }
5004         r_fb.water.renderingscene = false;
5005         r_refdef.view = originalview;
5006         R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
5007         R_View_Update();
5008         R_AnimCache_CacheVisibleEntities();
5009         goto finish;
5010 error:
5011         r_refdef.view = originalview;
5012         r_fb.water.renderingscene = false;
5013         Cvar_SetValueQuick(&r_water, 0);
5014         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5015 finish:
5016         // lowquality hack, restore cvars
5017         if (qualityreduction > 0)
5018         {
5019                 if (qualityreduction >= 1)
5020                 {
5021                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5022                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5023                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5024                 }
5025                 if (qualityreduction >= 2)
5026                 {
5027                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5028                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5029                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5030                 }
5031         }
5032 }
5033
5034 static void R_Bloom_StartFrame(void)
5035 {
5036         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5037         int viewwidth, viewheight;
5038         textype_t textype = TEXTYPE_COLORBUFFER;
5039
5040         // clear the pointers to rendertargets from last frame as they're stale
5041         r_fb.rt_screen = NULL;
5042         r_fb.rt_bloom = NULL;
5043
5044         switch (vid.renderpath)
5045         {
5046         case RENDERPATH_GL32:
5047                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5048                 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5049                 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5050                 break;
5051         case RENDERPATH_GLES2:
5052                 r_fb.usedepthtextures = false;
5053                 break;
5054         }
5055
5056         if (r_viewscale_fpsscaling.integer)
5057         {
5058                 double actualframetime;
5059                 double targetframetime;
5060                 double adjust;
5061                 actualframetime = r_refdef.lastdrawscreentime;
5062                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5063                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5064                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5065                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5066                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5067                 viewscalefpsadjusted += adjust;
5068                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5069         }
5070         else
5071                 viewscalefpsadjusted = 1.0f;
5072
5073         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5074
5075         // set bloomwidth and bloomheight to the bloom resolution that will be
5076         // used (often less than the screen resolution for faster rendering)
5077         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
5078         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
5079         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
5080         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
5081         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
5082
5083         // calculate desired texture sizes
5084         screentexturewidth = viewwidth;
5085         screentextureheight = viewheight;
5086         bloomtexturewidth = r_fb.bloomwidth;
5087         bloomtextureheight = r_fb.bloomheight;
5088
5089         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))
5090         {
5091                 Cvar_SetValueQuick(&r_bloom, 0);
5092                 Cvar_SetValueQuick(&r_motionblur, 0);
5093                 Cvar_SetValueQuick(&r_damageblur, 0);
5094         }
5095
5096         // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
5097         if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
5098         {
5099                 if (r_fb.ghosttexture)
5100                         R_FreeTexture(r_fb.ghosttexture);
5101                 r_fb.ghosttexture = NULL;
5102
5103                 r_fb.screentexturewidth = screentexturewidth;
5104                 r_fb.screentextureheight = screentextureheight;
5105                 r_fb.textype = textype;
5106
5107                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
5108                 {
5109                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
5110                                 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);
5111                         r_fb.ghosttexture_valid = false;
5112                 }
5113         }
5114
5115         if (r_bloom.integer)
5116         {
5117                 // bloom texture is a different resolution
5118                 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
5119                 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5120                 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
5121         }
5122         else
5123                 r_fb.bloomwidth = r_fb.bloomheight = 0;
5124
5125         r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5126
5127         r_refdef.view.clear = true;
5128 }
5129
5130 static void R_Bloom_MakeTexture(void)
5131 {
5132         int x, range, dir;
5133         float xoffset, yoffset, r, brighten;
5134         float colorscale = r_bloom_colorscale.value;
5135         r_viewport_t bloomviewport;
5136         r_rendertarget_t *prev, *cur;
5137         textype_t textype = r_fb.rt_screen->colortextype[0];
5138
5139         r_refdef.stats[r_stat_bloom]++;
5140
5141         R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5142
5143         // scale down screen texture to the bloom texture size
5144         CHECKGLERROR
5145         prev = r_fb.rt_screen;
5146         cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5147         R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5148         R_SetViewport(&bloomviewport);
5149         GL_CullFace(GL_NONE);
5150         GL_DepthTest(false);
5151         GL_BlendFunc(GL_ONE, GL_ZERO);
5152         GL_Color(colorscale, colorscale, colorscale, 1);
5153         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5154         // TODO: do boxfilter scale-down in shader?
5155         R_SetupShader_Generic(prev->colortexture[0], false, true, true);
5156         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5157         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5158         // we now have a properly scaled bloom image
5159
5160         // multiply bloom image by itself as many times as desired to darken it
5161         // TODO: if people actually use this it could be done more quickly in the previous shader pass
5162         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5163         {
5164                 prev = cur;
5165                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5166                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5167                 x *= 2;
5168                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
5169                 if(x <= 2)
5170                         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
5171                 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
5172                 GL_Color(1,1,1,1); // no fix factor supported here
5173                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
5174                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5175                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5176                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5177         }
5178         CHECKGLERROR
5179
5180         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
5181         brighten = r_bloom_brighten.value;
5182         brighten = sqrt(brighten);
5183         if(range >= 1)
5184                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5185
5186         for (dir = 0;dir < 2;dir++)
5187         {
5188                 prev = cur;
5189                 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
5190                 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
5191                 // blend on at multiple vertical offsets to achieve a vertical blur
5192                 // TODO: do offset blends using GLSL
5193                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5194                 CHECKGLERROR
5195                 GL_BlendFunc(GL_ONE, GL_ZERO);
5196                 CHECKGLERROR
5197                 R_SetupShader_Generic(prev->colortexture[0], false, true, false);
5198                 CHECKGLERROR
5199                 for (x = -range;x <= range;x++)
5200                 {
5201                         if (!dir){xoffset = 0;yoffset = x;}
5202                         else {xoffset = x;yoffset = 0;}
5203                         xoffset /= (float)prev->texturewidth;
5204                         yoffset /= (float)prev->textureheight;
5205                         // compute a texcoord array with the specified x and y offset
5206                         r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
5207                         r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
5208                         r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
5209                         r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
5210                         r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
5211                         r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
5212                         r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
5213                         r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
5214                         // this r value looks like a 'dot' particle, fading sharply to
5215                         // black at the edges
5216                         // (probably not realistic but looks good enough)
5217                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5218                         //r = brighten/(range*2+1);
5219                         r = brighten / (range * 2 + 1);
5220                         if(range >= 1)
5221                                 r *= (1 - x*x/(float)((range+1)*(range+1)));
5222                         if (r <= 0)
5223                                 continue;
5224                         CHECKGLERROR
5225                         GL_Color(r, r, r, 1);
5226                         CHECKGLERROR
5227                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
5228                         CHECKGLERROR
5229                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5230                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
5231                         CHECKGLERROR
5232                         GL_BlendFunc(GL_ONE, GL_ONE);
5233                         CHECKGLERROR
5234                 }
5235         }
5236
5237         // now we have the bloom image, so keep track of it
5238         r_fb.rt_bloom = cur;
5239 }
5240
5241 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5242 {
5243         dpuint64 permutation;
5244         float uservecs[4][4];
5245         rtexture_t *viewtexture;
5246         rtexture_t *bloomtexture;
5247
5248         R_EntityMatrix(&identitymatrix);
5249
5250         if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
5251         {
5252                 // declare variables
5253                 float blur_factor, blur_mouseaccel, blur_velocity;
5254                 static float blur_average; 
5255                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
5256
5257                 // set a goal for the factoring
5258                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
5259                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
5260                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
5261                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
5262                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
5263                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
5264
5265                 // from the goal, pick an averaged value between goal and last value
5266                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
5267                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
5268
5269                 // enforce minimum amount of blur 
5270                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
5271
5272                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
5273
5274                 // calculate values into a standard alpha
5275                 cl.motionbluralpha = 1 - exp(-
5276                                 (
5277                                         (r_motionblur.value * blur_factor / 80)
5278                                         +
5279                                         (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5280                                 )
5281                                 /
5282                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5283                                 );
5284
5285                 // randomization for the blur value to combat persistent ghosting
5286                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5287                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5288
5289                 // apply the blur
5290                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5291                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
5292                 {
5293                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5294                         GL_Color(1, 1, 1, cl.motionbluralpha);
5295                         R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
5296                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
5297                         R_SetupShader_Generic(r_fb.ghosttexture, false, true, true);
5298                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5299                         r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
5300                 }
5301
5302                 // updates old view angles for next pass
5303                 VectorCopy(cl.viewangles, blur_oldangles);
5304
5305                 // copy view into the ghost texture
5306                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
5307                 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
5308                 r_fb.ghosttexture_valid = true;
5309         }
5310
5311         if (r_fb.bloomwidth)
5312         {
5313                 // make the bloom texture
5314                 R_Bloom_MakeTexture();
5315         }
5316
5317 #if _MSC_VER >= 1400
5318 #define sscanf sscanf_s
5319 #endif
5320         memset(uservecs, 0, sizeof(uservecs));
5321         if (r_glsl_postprocess_uservec1_enable.integer)
5322                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5323         if (r_glsl_postprocess_uservec2_enable.integer)
5324                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5325         if (r_glsl_postprocess_uservec3_enable.integer)
5326                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5327         if (r_glsl_postprocess_uservec4_enable.integer)
5328                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5329
5330         // render to the screen fbo
5331         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5332         GL_Color(1, 1, 1, 1);
5333         GL_BlendFunc(GL_ONE, GL_ZERO);
5334
5335         viewtexture = r_fb.rt_screen->colortexture[0];
5336         bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
5337
5338         if (r_rendertarget_debug.integer >= 0)
5339         {
5340                 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
5341                 if (rt && rt->colortexture[0])
5342                 {
5343                         viewtexture = rt->colortexture[0];
5344                         bloomtexture = NULL;
5345                 }
5346         }
5347
5348         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
5349         switch(vid.renderpath)
5350         {
5351         case RENDERPATH_GL32:
5352         case RENDERPATH_GLES2:
5353                 permutation =
5354                         (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
5355                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5356                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
5357                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5358                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5359                 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5360                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , viewtexture);
5361                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , bloomtexture);
5362                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
5363                 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]);
5364                 if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
5365                 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]);
5366                 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]);
5367                 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]);
5368                 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]);
5369                 if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5370                 if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5371                 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);
5372                 break;
5373         }
5374         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5375         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
5376 }
5377
5378 matrix4x4_t r_waterscrollmatrix;
5379
5380 void R_UpdateFog(void)
5381 {
5382         // Nehahra fog
5383         if (gamemode == GAME_NEHAHRA)
5384         {
5385                 if (gl_fogenable.integer)
5386                 {
5387                         r_refdef.oldgl_fogenable = true;
5388                         r_refdef.fog_density = gl_fogdensity.value;
5389                         r_refdef.fog_red = gl_fogred.value;
5390                         r_refdef.fog_green = gl_foggreen.value;
5391                         r_refdef.fog_blue = gl_fogblue.value;
5392                         r_refdef.fog_alpha = 1;
5393                         r_refdef.fog_start = 0;
5394                         r_refdef.fog_end = gl_skyclip.value;
5395                         r_refdef.fog_height = 1<<30;
5396                         r_refdef.fog_fadedepth = 128;
5397                 }
5398                 else if (r_refdef.oldgl_fogenable)
5399                 {
5400                         r_refdef.oldgl_fogenable = false;
5401                         r_refdef.fog_density = 0;
5402                         r_refdef.fog_red = 0;
5403                         r_refdef.fog_green = 0;
5404                         r_refdef.fog_blue = 0;
5405                         r_refdef.fog_alpha = 0;
5406                         r_refdef.fog_start = 0;
5407                         r_refdef.fog_end = 0;
5408                         r_refdef.fog_height = 1<<30;
5409                         r_refdef.fog_fadedepth = 128;
5410                 }
5411         }
5412
5413         // fog parms
5414         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5415         r_refdef.fog_start = max(0, r_refdef.fog_start);
5416         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5417
5418         if (r_refdef.fog_density && r_drawfog.integer)
5419         {
5420                 r_refdef.fogenabled = true;
5421                 // this is the point where the fog reaches 0.9986 alpha, which we
5422                 // consider a good enough cutoff point for the texture
5423                 // (0.9986 * 256 == 255.6)
5424                 if (r_fog_exp2.integer)
5425                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5426                 else
5427                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5428                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5429                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5430                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5431                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
5432                         R_BuildFogHeightTexture();
5433                 // fog color was already set
5434                 // update the fog texture
5435                 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)
5436                         R_BuildFogTexture();
5437                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
5438                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
5439         }
5440         else
5441                 r_refdef.fogenabled = false;
5442
5443         // fog color
5444         if (r_refdef.fog_density)
5445         {
5446                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5447                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5448                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5449
5450                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5451                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5452                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5453                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5454
5455                 {
5456                         vec3_t fogvec;
5457                         VectorCopy(r_refdef.fogcolor, fogvec);
5458                         //   color.rgb *= ContrastBoost * SceneBrightness;
5459                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5460                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5461                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5462                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5463                 }
5464         }
5465 }
5466
5467 void R_UpdateVariables(void)
5468 {
5469         R_Textures_Frame();
5470
5471         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
5472
5473         r_refdef.farclip = r_farclip_base.value;
5474         if (r_refdef.scene.worldmodel)
5475                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5476         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5477
5478         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5479                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5480         r_refdef.polygonfactor = 0;
5481         r_refdef.polygonoffset = 0;
5482
5483         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5484         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5485         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
5486         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5487         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5488         if (r_refdef.scene.worldmodel)
5489         {
5490                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
5491         }
5492         if (r_showsurfaces.integer)
5493         {
5494                 r_refdef.scene.rtworld = false;
5495                 r_refdef.scene.rtworldshadows = false;
5496                 r_refdef.scene.rtdlight = false;
5497                 r_refdef.scene.rtdlightshadows = false;
5498                 r_refdef.scene.lightmapintensity = 0;
5499         }
5500
5501         r_gpuskeletal = false;
5502         switch(vid.renderpath)
5503         {
5504         case RENDERPATH_GL32:
5505                 r_gpuskeletal = r_glsl_skeletal.integer && !r_showsurfaces.integer;
5506         case RENDERPATH_GLES2:
5507                 if(!vid_gammatables_trivial)
5508                 {
5509                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5510                         {
5511                                 // build GLSL gamma texture
5512 #define RAMPWIDTH 256
5513                                 unsigned short ramp[RAMPWIDTH * 3];
5514                                 unsigned char rampbgr[RAMPWIDTH][4];
5515                                 int i;
5516
5517                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5518
5519                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5520                                 for(i = 0; i < RAMPWIDTH; ++i)
5521                                 {
5522                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5523                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5524                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5525                                         rampbgr[i][3] = 0;
5526                                 }
5527                                 if (r_texture_gammaramps)
5528                                 {
5529                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
5530                                 }
5531                                 else
5532                                 {
5533                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
5534                                 }
5535                         }
5536                 }
5537                 else
5538                 {
5539                         // remove GLSL gamma texture
5540                 }
5541                 break;
5542         }
5543 }
5544
5545 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5546 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5547 /*
5548 ================
5549 R_SelectScene
5550 ================
5551 */
5552 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5553         if( scenetype != r_currentscenetype ) {
5554                 // store the old scenetype
5555                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5556                 r_currentscenetype = scenetype;
5557                 // move in the new scene
5558                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5559         }
5560 }
5561
5562 /*
5563 ================
5564 R_GetScenePointer
5565 ================
5566 */
5567 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5568 {
5569         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5570         if( scenetype == r_currentscenetype ) {
5571                 return &r_refdef.scene;
5572         } else {
5573                 return &r_scenes_store[ scenetype ];
5574         }
5575 }
5576
5577 static int R_SortEntities_Compare(const void *ap, const void *bp)
5578 {
5579         const entity_render_t *a = *(const entity_render_t **)ap;
5580         const entity_render_t *b = *(const entity_render_t **)bp;
5581
5582         // 1. compare model
5583         if(a->model < b->model)
5584                 return -1;
5585         if(a->model > b->model)
5586                 return +1;
5587
5588         // 2. compare skin
5589         // TODO possibly calculate the REAL skinnum here first using
5590         // skinscenes?
5591         if(a->skinnum < b->skinnum)
5592                 return -1;
5593         if(a->skinnum > b->skinnum)
5594                 return +1;
5595
5596         // everything we compared is equal
5597         return 0;
5598 }
5599 static void R_SortEntities(void)
5600 {
5601         // below or equal 2 ents, sorting never gains anything
5602         if(r_refdef.scene.numentities <= 2)
5603                 return;
5604         // sort
5605         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
5606 }
5607
5608 /*
5609 ================
5610 R_RenderView
5611 ================
5612 */
5613 extern cvar_t r_shadow_bouncegrid;
5614 extern cvar_t v_isometric;
5615 extern void V_MakeViewIsometric(void);
5616 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
5617 {
5618         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
5619         int viewfbo = 0;
5620         rtexture_t *viewdepthtexture = NULL;
5621         rtexture_t *viewcolortexture = NULL;
5622         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
5623
5624         // finish any 2D rendering that was queued
5625         DrawQ_Finish();
5626
5627         if (r_timereport_active)
5628                 R_TimeReport("start");
5629         r_textureframe++; // used only by R_GetCurrentTexture
5630         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5631
5632         if(R_CompileShader_CheckStaticParms())
5633                 R_GLSL_Restart_f();
5634
5635         if (!r_drawentities.integer)
5636                 r_refdef.scene.numentities = 0;
5637         else if (r_sortentities.integer)
5638                 R_SortEntities();
5639
5640         R_AnimCache_ClearCache();
5641
5642         /* adjust for stereo display */
5643         if(R_Stereo_Active())
5644         {
5645                 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);
5646                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
5647         }
5648
5649         if (r_refdef.view.isoverlay)
5650         {
5651                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5652                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
5653                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
5654                 R_TimeReport("depthclear");
5655
5656                 r_refdef.view.showdebug = false;
5657
5658                 r_fb.water.enabled = false;
5659                 r_fb.water.numwaterplanes = 0;
5660
5661                 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5662
5663                 r_refdef.view.matrix = originalmatrix;
5664
5665                 CHECKGLERROR
5666                 return;
5667         }
5668
5669         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
5670         {
5671                 r_refdef.view.matrix = originalmatrix;
5672                 return;
5673         }
5674
5675         r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
5676         if (v_isometric.integer && r_refdef.view.ismain)
5677                 V_MakeViewIsometric();
5678
5679         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
5680
5681         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
5682                 // in sRGB fallback, behave similar to true sRGB: convert this
5683                 // value from linear to sRGB
5684                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
5685
5686         R_RenderView_UpdateViewVectors();
5687
5688         R_Shadow_UpdateWorldLightSelection();
5689
5690         // this will set up r_fb.rt_screen
5691         R_Bloom_StartFrame();
5692
5693         // apply bloom brightness offset
5694         if(r_fb.rt_bloom)
5695                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
5696
5697         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
5698         if (r_fb.rt_screen)
5699         {
5700                 viewfbo = r_fb.rt_screen->fbo;
5701                 viewdepthtexture = r_fb.rt_screen->depthtexture;
5702                 viewcolortexture = r_fb.rt_screen->colortexture[0];
5703                 viewx = 0;
5704                 viewy = 0;
5705                 viewwidth = width;
5706                 viewheight = height;
5707         }
5708
5709         R_Water_StartFrame();
5710
5711         CHECKGLERROR
5712         if (r_timereport_active)
5713                 R_TimeReport("viewsetup");
5714
5715         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5716
5717         // clear the whole fbo every frame - otherwise the driver will consider
5718         // it to be an inter-frame texture and stall in multi-gpu configurations
5719         if (r_fb.rt_screen)
5720                 GL_ScissorTest(false);
5721         R_ClearScreen(r_refdef.fogenabled);
5722         if (r_timereport_active)
5723                 R_TimeReport("viewclear");
5724
5725         r_refdef.view.clear = true;
5726
5727         r_refdef.view.showdebug = true;
5728
5729         R_View_Update();
5730         if (r_timereport_active)
5731                 R_TimeReport("visibility");
5732
5733         R_AnimCache_CacheVisibleEntities();
5734         if (r_timereport_active)
5735                 R_TimeReport("animcache");
5736
5737         R_Shadow_UpdateBounceGridTexture();
5738         if (r_timereport_active && r_shadow_bouncegrid.integer)
5739                 R_TimeReport("bouncegrid");
5740
5741         r_fb.water.numwaterplanes = 0;
5742         if (r_fb.water.enabled)
5743                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5744
5745         // for the actual view render we use scissoring a fair amount, so scissor
5746         // test needs to be on
5747         if (r_fb.rt_screen)
5748                 GL_ScissorTest(true);
5749         GL_Scissor(viewx, viewy, viewwidth, viewheight);
5750         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5751         r_fb.water.numwaterplanes = 0;
5752
5753         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
5754         GL_ScissorTest(false);
5755
5756         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
5757         if (r_timereport_active)
5758                 R_TimeReport("blendview");
5759
5760         r_refdef.view.matrix = originalmatrix;
5761
5762         CHECKGLERROR
5763
5764         // go back to 2d rendering
5765         DrawQ_Start();
5766 }
5767
5768 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5769 {
5770         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5771         {
5772                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5773                 if (r_timereport_active)
5774                         R_TimeReport("waterworld");
5775         }
5776
5777         // don't let sound skip if going slow
5778         if (r_refdef.scene.extraupdate)
5779                 S_ExtraUpdate ();
5780
5781         R_DrawModelsAddWaterPlanes();
5782         if (r_timereport_active)
5783                 R_TimeReport("watermodels");
5784
5785         if (r_fb.water.numwaterplanes)
5786         {
5787                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5788                 if (r_timereport_active)
5789                         R_TimeReport("waterscenes");
5790         }
5791 }
5792
5793 extern cvar_t cl_locs_show;
5794 static void R_DrawLocs(void);
5795 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
5796 static void R_DrawModelDecals(void);
5797 extern cvar_t cl_decals_newsystem;
5798 extern qboolean r_shadow_usingdeferredprepass;
5799 extern int r_shadow_shadowmapatlas_modelshadows_size;
5800 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5801 {
5802         qboolean shadowmapping = false;
5803
5804         if (r_timereport_active)
5805                 R_TimeReport("beginscene");
5806
5807         r_refdef.stats[r_stat_renders]++;
5808
5809         R_UpdateFog();
5810
5811         // don't let sound skip if going slow
5812         if (r_refdef.scene.extraupdate)
5813                 S_ExtraUpdate ();
5814
5815         R_MeshQueue_BeginScene();
5816
5817         R_SkyStartFrame();
5818
5819         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);
5820
5821         if (r_timereport_active)
5822                 R_TimeReport("skystartframe");
5823
5824         if (cl.csqc_vidvars.drawworld)
5825         {
5826                 // don't let sound skip if going slow
5827                 if (r_refdef.scene.extraupdate)
5828                         S_ExtraUpdate ();
5829
5830                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5831                 {
5832                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5833                         if (r_timereport_active)
5834                                 R_TimeReport("worldsky");
5835                 }
5836
5837                 if (R_DrawBrushModelsSky() && r_timereport_active)
5838                         R_TimeReport("bmodelsky");
5839
5840                 if (skyrendermasked && skyrenderlater)
5841                 {
5842                         // we have to force off the water clipping plane while rendering sky
5843                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5844                         R_Sky();
5845                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5846                         if (r_timereport_active)
5847                                 R_TimeReport("sky");
5848                 }
5849         }
5850
5851         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
5852         r_shadow_viewfbo = viewfbo;
5853         r_shadow_viewdepthtexture = viewdepthtexture;
5854         r_shadow_viewcolortexture = viewcolortexture;
5855         r_shadow_viewx = viewx;
5856         r_shadow_viewy = viewy;
5857         r_shadow_viewwidth = viewwidth;
5858         r_shadow_viewheight = viewheight;
5859
5860         R_Shadow_PrepareModelShadows();
5861         R_Shadow_PrepareLights();
5862         if (r_timereport_active)
5863                 R_TimeReport("preparelights");
5864
5865         // render all the shadowmaps that will be used for this view
5866         shadowmapping = R_Shadow_ShadowMappingEnabled();
5867         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
5868         {
5869                 R_Shadow_DrawShadowMaps();
5870                 if (r_timereport_active)
5871                         R_TimeReport("shadowmaps");
5872         }
5873
5874         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
5875         if (r_shadow_usingdeferredprepass)
5876                 R_Shadow_DrawPrepass();
5877
5878         // now we begin the forward pass of the view render
5879         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5880         {
5881                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5882                 if (r_timereport_active)
5883                         R_TimeReport("worlddepth");
5884         }
5885         if (r_depthfirst.integer >= 2)
5886         {
5887                 R_DrawModelsDepth();
5888                 if (r_timereport_active)
5889                         R_TimeReport("modeldepth");
5890         }
5891
5892         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5893         {
5894                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5895                 if (r_timereport_active)
5896                         R_TimeReport("world");
5897         }
5898
5899         // don't let sound skip if going slow
5900         if (r_refdef.scene.extraupdate)
5901                 S_ExtraUpdate ();
5902
5903         R_DrawModels();
5904         if (r_timereport_active)
5905                 R_TimeReport("models");
5906
5907         // don't let sound skip if going slow
5908         if (r_refdef.scene.extraupdate)
5909                 S_ExtraUpdate ();
5910
5911         if (!r_shadow_usingdeferredprepass)
5912         {
5913                 R_Shadow_DrawLights();
5914                 if (r_timereport_active)
5915                         R_TimeReport("rtlights");
5916         }
5917
5918         // don't let sound skip if going slow
5919         if (r_refdef.scene.extraupdate)
5920                 S_ExtraUpdate ();
5921
5922         if (cl.csqc_vidvars.drawworld)
5923         {
5924                 if (cl_decals_newsystem.integer)
5925                 {
5926                         R_DrawModelDecals();
5927                         if (r_timereport_active)
5928                                 R_TimeReport("modeldecals");
5929                 }
5930                 else
5931                 {
5932                         R_DrawDecals();
5933                         if (r_timereport_active)
5934                                 R_TimeReport("decals");
5935                 }
5936
5937                 R_DrawParticles();
5938                 if (r_timereport_active)
5939                         R_TimeReport("particles");
5940
5941                 R_DrawExplosions();
5942                 if (r_timereport_active)
5943                         R_TimeReport("explosions");
5944         }
5945
5946         if (r_refdef.view.showdebug)
5947         {
5948                 if (cl_locs_show.integer)
5949                 {
5950                         R_DrawLocs();
5951                         if (r_timereport_active)
5952                                 R_TimeReport("showlocs");
5953                 }
5954
5955                 if (r_drawportals.integer)
5956                 {
5957                         R_DrawPortals();
5958                         if (r_timereport_active)
5959                                 R_TimeReport("portals");
5960                 }
5961
5962                 if (r_showbboxes_client.value > 0)
5963                 {
5964                         R_DrawEntityBBoxes(CLVM_prog);
5965                         if (r_timereport_active)
5966                                 R_TimeReport("clbboxes");
5967                 }
5968                 if (r_showbboxes.value > 0)
5969                 {
5970                         R_DrawEntityBBoxes(SVVM_prog);
5971                         if (r_timereport_active)
5972                                 R_TimeReport("svbboxes");
5973                 }
5974         }
5975
5976         if (r_transparent.integer)
5977         {
5978                 R_MeshQueue_RenderTransparent();
5979                 if (r_timereport_active)
5980                         R_TimeReport("drawtrans");
5981         }
5982
5983         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))
5984         {
5985                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5986                 if (r_timereport_active)
5987                         R_TimeReport("worlddebug");
5988                 R_DrawModelsDebug();
5989                 if (r_timereport_active)
5990                         R_TimeReport("modeldebug");
5991         }
5992
5993         if (cl.csqc_vidvars.drawworld)
5994         {
5995                 R_Shadow_DrawCoronas();
5996                 if (r_timereport_active)
5997                         R_TimeReport("coronas");
5998         }
5999
6000         // don't let sound skip if going slow
6001         if (r_refdef.scene.extraupdate)
6002                 S_ExtraUpdate ();
6003 }
6004
6005 static const unsigned short bboxelements[36] =
6006 {
6007         5, 1, 3, 5, 3, 7,
6008         6, 2, 0, 6, 0, 4,
6009         7, 3, 2, 7, 2, 6,
6010         4, 0, 1, 4, 1, 5,
6011         4, 5, 7, 4, 7, 6,
6012         1, 0, 2, 1, 2, 3,
6013 };
6014
6015 #define BBOXEDGES 13
6016 static const float bboxedges[BBOXEDGES][6] = 
6017 {
6018         // whole box
6019         { 0, 0, 0, 1, 1, 1 },
6020         // bottom edges
6021         { 0, 0, 0, 0, 1, 0 },
6022         { 0, 0, 0, 1, 0, 0 },
6023         { 0, 1, 0, 1, 1, 0 },
6024         { 1, 0, 0, 1, 1, 0 },
6025         // top edges
6026         { 0, 0, 1, 0, 1, 1 },
6027         { 0, 0, 1, 1, 0, 1 },
6028         { 0, 1, 1, 1, 1, 1 },
6029         { 1, 0, 1, 1, 1, 1 },
6030         // vertical edges
6031         { 0, 0, 0, 0, 0, 1 },
6032         { 1, 0, 0, 1, 0, 1 },
6033         { 0, 1, 0, 0, 1, 1 },
6034         { 1, 1, 0, 1, 1, 1 },
6035 };
6036
6037 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6038 {
6039         int numvertices = BBOXEDGES * 8;
6040         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
6041         int numtriangles = BBOXEDGES * 12;
6042         unsigned short elements[BBOXEDGES * 36];
6043         int i, edge;
6044         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
6045
6046         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
6047
6048         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6049         GL_DepthMask(false);
6050         GL_DepthRange(0, 1);
6051         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6052
6053         for (edge = 0; edge < BBOXEDGES; edge++)
6054         {
6055                 for (i = 0; i < 3; i++)
6056                 {
6057                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
6058                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
6059                 }
6060                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
6061                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
6062                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
6063                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
6064                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
6065                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
6066                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
6067                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
6068                 for (i = 0; i < 36; i++)
6069                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
6070         }
6071         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
6072         if (r_refdef.fogenabled)
6073         {
6074                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
6075                 {
6076                         f1 = RSurf_FogVertex(v);
6077                         f2 = 1 - f1;
6078                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6079                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6080                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6081                 }
6082         }
6083         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
6084         R_Mesh_ResetTextureState();
6085         R_SetupShader_Generic_NoTexture(false, false);
6086         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
6087 }
6088
6089 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6090 {
6091         // hacky overloading of the parameters
6092         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
6093         int i;
6094         float color[4];
6095         prvm_edict_t *edict;
6096
6097         GL_CullFace(GL_NONE);
6098         R_SetupShader_Generic_NoTexture(false, false);
6099
6100         for (i = 0;i < numsurfaces;i++)
6101         {
6102                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6103                 switch ((int)PRVM_serveredictfloat(edict, solid))
6104                 {
6105                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6106                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6107                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6108                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6109                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6110                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
6111                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6112                 }
6113                 if (prog == CLVM_prog)
6114                         color[3] *= r_showbboxes_client.value;
6115                 else
6116                         color[3] *= r_showbboxes.value;
6117                 color[3] = bound(0, color[3], 1);
6118                 GL_DepthTest(!r_showdisabledepthtest.integer);
6119                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6120         }
6121 }
6122
6123 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
6124 {
6125         int i;
6126         prvm_edict_t *edict;
6127         vec3_t center;
6128
6129         if (prog == NULL)
6130                 return;
6131
6132         for (i = 0; i < prog->num_edicts; i++)
6133         {
6134                 edict = PRVM_EDICT_NUM(i);
6135                 if (edict->priv.server->free)
6136                         continue;
6137                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6138                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
6139                         continue;
6140                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
6141                         continue;
6142                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6143                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
6144         }
6145 }
6146
6147 static const int nomodelelement3i[24] =
6148 {
6149         5, 2, 0,
6150         5, 1, 2,
6151         5, 0, 3,
6152         5, 3, 1,
6153         0, 2, 4,
6154         2, 1, 4,
6155         3, 0, 4,
6156         1, 3, 4
6157 };
6158
6159 static const unsigned short nomodelelement3s[24] =
6160 {
6161         5, 2, 0,
6162         5, 1, 2,
6163         5, 0, 3,
6164         5, 3, 1,
6165         0, 2, 4,
6166         2, 1, 4,
6167         3, 0, 4,
6168         1, 3, 4
6169 };
6170
6171 static const float nomodelvertex3f[6*3] =
6172 {
6173         -16,   0,   0,
6174          16,   0,   0,
6175           0, -16,   0,
6176           0,  16,   0,
6177           0,   0, -16,
6178           0,   0,  16
6179 };
6180
6181 static const float nomodelcolor4f[6*4] =
6182 {
6183         0.0f, 0.0f, 0.5f, 1.0f,
6184         0.0f, 0.0f, 0.5f, 1.0f,
6185         0.0f, 0.5f, 0.0f, 1.0f,
6186         0.0f, 0.5f, 0.0f, 1.0f,
6187         0.5f, 0.0f, 0.0f, 1.0f,
6188         0.5f, 0.0f, 0.0f, 1.0f
6189 };
6190
6191 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6192 {
6193         int i;
6194         float f1, f2, *c;
6195         float color4f[6*4];
6196
6197         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);
6198
6199         // this is only called once per entity so numsurfaces is always 1, and
6200         // surfacelist is always {0}, so this code does not handle batches
6201
6202         if (rsurface.ent_flags & RENDER_ADDITIVE)
6203         {
6204                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6205                 GL_DepthMask(false);
6206         }
6207         else if (ent->alpha < 1)
6208         {
6209                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6210                 GL_DepthMask(false);
6211         }
6212         else
6213         {
6214                 GL_BlendFunc(GL_ONE, GL_ZERO);
6215                 GL_DepthMask(true);
6216         }
6217         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6218         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6219         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6220         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6221         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6222         for (i = 0, c = color4f;i < 6;i++, c += 4)
6223         {
6224                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
6225                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
6226                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
6227                 c[3] *= ent->alpha;
6228         }
6229         if (r_refdef.fogenabled)
6230         {
6231                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6232                 {
6233                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6234                         f2 = 1 - f1;
6235                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6236                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6237                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6238                 }
6239         }
6240 //      R_Mesh_ResetTextureState();
6241         R_SetupShader_Generic_NoTexture(false, false);
6242         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6243         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6244 }
6245
6246 void R_DrawNoModel(entity_render_t *ent)
6247 {
6248         vec3_t org;
6249         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6250         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6251                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6252         else
6253                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6254 }
6255
6256 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
6257 {
6258         vec3_t right1, right2, diff, normal;
6259
6260         VectorSubtract (org2, org1, normal);
6261
6262         // calculate 'right' vector for start
6263         VectorSubtract (r_refdef.view.origin, org1, diff);
6264         CrossProduct (normal, diff, right1);
6265         VectorNormalize (right1);
6266
6267         // calculate 'right' vector for end
6268         VectorSubtract (r_refdef.view.origin, org2, diff);
6269         CrossProduct (normal, diff, right2);
6270         VectorNormalize (right2);
6271
6272         vert[ 0] = org1[0] + width * right1[0];
6273         vert[ 1] = org1[1] + width * right1[1];
6274         vert[ 2] = org1[2] + width * right1[2];
6275         vert[ 3] = org1[0] - width * right1[0];
6276         vert[ 4] = org1[1] - width * right1[1];
6277         vert[ 5] = org1[2] - width * right1[2];
6278         vert[ 6] = org2[0] - width * right2[0];
6279         vert[ 7] = org2[1] - width * right2[1];
6280         vert[ 8] = org2[2] - width * right2[2];
6281         vert[ 9] = org2[0] + width * right2[0];
6282         vert[10] = org2[1] + width * right2[1];
6283         vert[11] = org2[2] + width * right2[2];
6284 }
6285
6286 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)
6287 {
6288         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6289         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6290         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6291         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6292         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6293         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6294         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6295         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6296         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6297         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6298         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6299         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6300 }
6301
6302 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6303 {
6304         int i;
6305         float *vertex3f;
6306         float v[3];
6307         VectorSet(v, x, y, z);
6308         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6309                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6310                         break;
6311         if (i == mesh->numvertices)
6312         {
6313                 if (mesh->numvertices < mesh->maxvertices)
6314                 {
6315                         VectorCopy(v, vertex3f);
6316                         mesh->numvertices++;
6317                 }
6318                 return mesh->numvertices;
6319         }
6320         else
6321                 return i;
6322 }
6323
6324 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6325 {
6326         int i;
6327         int *e, element[3];
6328         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6329         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6330         e = mesh->element3i + mesh->numtriangles * 3;
6331         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6332         {
6333                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6334                 if (mesh->numtriangles < mesh->maxtriangles)
6335                 {
6336                         *e++ = element[0];
6337                         *e++ = element[1];
6338                         *e++ = element[2];
6339                         mesh->numtriangles++;
6340                 }
6341                 element[1] = element[2];
6342         }
6343 }
6344
6345 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6346 {
6347         int i;
6348         int *e, element[3];
6349         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6350         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6351         e = mesh->element3i + mesh->numtriangles * 3;
6352         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6353         {
6354                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6355                 if (mesh->numtriangles < mesh->maxtriangles)
6356                 {
6357                         *e++ = element[0];
6358                         *e++ = element[1];
6359                         *e++ = element[2];
6360                         mesh->numtriangles++;
6361                 }
6362                 element[1] = element[2];
6363         }
6364 }
6365
6366 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6367 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6368 {
6369         int planenum, planenum2;
6370         int w;
6371         int tempnumpoints;
6372         mplane_t *plane, *plane2;
6373         double maxdist;
6374         double temppoints[2][256*3];
6375         // figure out how large a bounding box we need to properly compute this brush
6376         maxdist = 0;
6377         for (w = 0;w < numplanes;w++)
6378                 maxdist = max(maxdist, fabs(planes[w].dist));
6379         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6380         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6381         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6382         {
6383                 w = 0;
6384                 tempnumpoints = 4;
6385                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6386                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6387                 {
6388                         if (planenum2 == planenum)
6389                                 continue;
6390                         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);
6391                         w = !w;
6392                 }
6393                 if (tempnumpoints < 3)
6394                         continue;
6395                 // generate elements forming a triangle fan for this polygon
6396                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6397         }
6398 }
6399
6400 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)
6401 {
6402         texturelayer_t *layer;
6403         layer = t->currentlayers + t->currentnumlayers++;
6404         layer->type = type;
6405         layer->depthmask = depthmask;
6406         layer->blendfunc1 = blendfunc1;
6407         layer->blendfunc2 = blendfunc2;
6408         layer->texture = texture;
6409         layer->texmatrix = *matrix;
6410         layer->color[0] = r;
6411         layer->color[1] = g;
6412         layer->color[2] = b;
6413         layer->color[3] = a;
6414 }
6415
6416 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
6417 {
6418         if(parms[0] == 0 && parms[1] == 0)
6419                 return false;
6420         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6421                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
6422                         return false;
6423         return true;
6424 }
6425
6426 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6427 {
6428         double index, f;
6429         index = parms[2] + rsurface.shadertime * parms[3];
6430         index -= floor(index);
6431         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
6432         {
6433         default:
6434         case Q3WAVEFUNC_NONE:
6435         case Q3WAVEFUNC_NOISE:
6436         case Q3WAVEFUNC_COUNT:
6437                 f = 0;
6438                 break;
6439         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6440         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6441         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6442         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6443         case Q3WAVEFUNC_TRIANGLE:
6444                 index *= 4;
6445                 f = index - floor(index);
6446                 if (index < 1)
6447                 {
6448                         // f = f;
6449                 }
6450                 else if (index < 2)
6451                         f = 1 - f;
6452                 else if (index < 3)
6453                         f = -f;
6454                 else
6455                         f = -(1 - f);
6456                 break;
6457         }
6458         f = parms[0] + parms[1] * f;
6459         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
6460                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
6461         return (float) f;
6462 }
6463
6464 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6465 {
6466         int w, h, idx;
6467         float shadertime;
6468         float f;
6469         float offsetd[2];
6470         float tcmat[12];
6471         matrix4x4_t matrix, temp;
6472         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
6473         // it's better to have one huge fixup every 9 hours than gradual
6474         // degradation over time which looks consistently bad after many hours.
6475         //
6476         // tcmod scroll in particular suffers from this degradation which can't be
6477         // effectively worked around even with floor() tricks because we don't
6478         // know if tcmod scroll is the last tcmod being applied, and for clampmap
6479         // a workaround involving floor() would be incorrect anyway...
6480         shadertime = rsurface.shadertime;
6481         if (shadertime >= 32768.0f)
6482                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
6483         switch(tcmod->tcmod)
6484         {
6485                 case Q3TCMOD_COUNT:
6486                 case Q3TCMOD_NONE:
6487                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6488                                 matrix = r_waterscrollmatrix;
6489                         else
6490                                 matrix = identitymatrix;
6491                         break;
6492                 case Q3TCMOD_ENTITYTRANSLATE:
6493                         // this is used in Q3 to allow the gamecode to control texcoord
6494                         // scrolling on the entity, which is not supported in darkplaces yet.
6495                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6496                         break;
6497                 case Q3TCMOD_ROTATE:
6498                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6499                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
6500                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6501                         break;
6502                 case Q3TCMOD_SCALE:
6503                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6504                         break;
6505                 case Q3TCMOD_SCROLL:
6506                         // this particular tcmod is a "bug for bug" compatible one with regards to
6507                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
6508                         // specifically did the wrapping and so we must mimic that...
6509                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
6510                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
6511                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
6512                         break;
6513                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6514                         w = (int) tcmod->parms[0];
6515                         h = (int) tcmod->parms[1];
6516                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
6517                         f = f - floor(f);
6518                         idx = (int) floor(f * w * h);
6519                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6520                         break;
6521                 case Q3TCMOD_STRETCH:
6522                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6523                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6524                         break;
6525                 case Q3TCMOD_TRANSFORM:
6526                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6527                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6528                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6529                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6530                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6531                         break;
6532                 case Q3TCMOD_TURBULENT:
6533                         // this is handled in the RSurf_PrepareVertices function
6534                         matrix = identitymatrix;
6535                         break;
6536         }
6537         temp = *texmatrix;
6538         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6539 }
6540
6541 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6542 {
6543         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
6544         char name[MAX_QPATH];
6545         skinframe_t *skinframe;
6546         unsigned char pixels[296*194];
6547         strlcpy(cache->name, skinname, sizeof(cache->name));
6548         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6549         if (developer_loading.integer)
6550                 Con_Printf("loading %s\n", name);
6551         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6552         if (!skinframe || !skinframe->base)
6553         {
6554                 unsigned char *f;
6555                 fs_offset_t filesize;
6556                 skinframe = NULL;
6557                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6558                 if (f)
6559                 {
6560                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
6561                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6562                         Mem_Free(f);
6563                 }
6564         }
6565         cache->skinframe = skinframe;
6566 }
6567
6568 texture_t *R_GetCurrentTexture(texture_t *t)
6569 {
6570         int i, q;
6571         const entity_render_t *ent = rsurface.entity;
6572         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
6573         q3shaderinfo_layer_tcmod_t *tcmod;
6574         float specularscale = 0.0f;
6575
6576         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
6577                 return t->currentframe;
6578         t->update_lastrenderframe = r_textureframe;
6579         t->update_lastrenderentity = (void *)ent;
6580
6581         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
6582                 t->camera_entity = ent->entitynumber;
6583         else
6584                 t->camera_entity = 0;
6585
6586         // switch to an alternate material if this is a q1bsp animated material
6587         {
6588                 texture_t *texture = t;
6589                 int s = rsurface.ent_skinnum;
6590                 if ((unsigned int)s >= (unsigned int)model->numskins)
6591                         s = 0;
6592                 if (model->skinscenes)
6593                 {
6594                         if (model->skinscenes[s].framecount > 1)
6595                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6596                         else
6597                                 s = model->skinscenes[s].firstframe;
6598                 }
6599                 if (s > 0)
6600                         t = t + s * model->num_surfaces;
6601                 if (t->animated)
6602                 {
6603                         // use an alternate animation if the entity's frame is not 0,
6604                         // and only if the texture has an alternate animation
6605                         if (t->animated == 2) // q2bsp
6606                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
6607                         else if (rsurface.ent_alttextures && t->anim_total[1])
6608                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
6609                         else
6610                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
6611                 }
6612                 texture->currentframe = t;
6613         }
6614
6615         // update currentskinframe to be a qw skin or animation frame
6616         if (rsurface.ent_qwskin >= 0)
6617         {
6618                 i = rsurface.ent_qwskin;
6619                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6620                 {
6621                         r_qwskincache_size = cl.maxclients;
6622                         if (r_qwskincache)
6623                                 Mem_Free(r_qwskincache);
6624                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6625                 }
6626                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6627                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6628                 t->currentskinframe = r_qwskincache[i].skinframe;
6629                 if (t->materialshaderpass && t->currentskinframe == NULL)
6630                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6631         }
6632         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
6633                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
6634         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
6635                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
6636
6637         t->currentmaterialflags = t->basematerialflags;
6638         t->currentalpha = rsurface.entity->alpha * t->basealpha;
6639         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_water.integer || r_novis.integer || r_trippy.integer))
6640                 t->currentalpha *= r_wateralpha.value;
6641         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
6642                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
6643         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
6644                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
6645
6646         // decide on which type of lighting to use for this surface
6647         if (rsurface.entity->render_modellight_forced)
6648                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6649         if (rsurface.entity->render_rtlight_disabled)
6650                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
6651         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
6652         {
6653                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
6654                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
6655                 for (q = 0; q < 3; q++)
6656                 {
6657                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
6658                         t->render_modellight_lightdir[q] = q == 2;
6659                         t->render_modellight_ambient[q] = 1;
6660                         t->render_modellight_diffuse[q] = 0;
6661                         t->render_modellight_specular[q] = 0;
6662                         t->render_lightmap_ambient[q] = 0;
6663                         t->render_lightmap_diffuse[q] = 0;
6664                         t->render_lightmap_specular[q] = 0;
6665                         t->render_rtlight_diffuse[q] = 0;
6666                         t->render_rtlight_specular[q] = 0;
6667                 }
6668         }
6669         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
6670         {
6671                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
6672                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
6673                 for (q = 0; q < 3; q++)
6674                 {
6675                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6676                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6677                         t->render_modellight_lightdir[q] = q == 2;
6678                         t->render_modellight_diffuse[q] = 0;
6679                         t->render_modellight_specular[q] = 0;
6680                         t->render_lightmap_ambient[q] = 0;
6681                         t->render_lightmap_diffuse[q] = 0;
6682                         t->render_lightmap_specular[q] = 0;
6683                         t->render_rtlight_diffuse[q] = 0;
6684                         t->render_rtlight_specular[q] = 0;
6685                 }
6686         }
6687         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
6688         {
6689                 // ambient + single direction light (modellight)
6690                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6691                 for (q = 0; q < 3; q++)
6692                 {
6693                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6694                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
6695                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
6696                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
6697                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
6698                         t->render_lightmap_ambient[q] = 0;
6699                         t->render_lightmap_diffuse[q] = 0;
6700                         t->render_lightmap_specular[q] = 0;
6701                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6702                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6703                 }
6704         }
6705         else
6706         {
6707                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
6708                 for (q = 0; q < 3; q++)
6709                 {
6710                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6711                         t->render_modellight_lightdir[q] = q == 2;
6712                         t->render_modellight_ambient[q] = 0;
6713                         t->render_modellight_diffuse[q] = 0;
6714                         t->render_modellight_specular[q] = 0;
6715                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
6716                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
6717                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
6718                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
6719                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
6720                 }
6721         }
6722
6723         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
6724         {
6725                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
6726                 // attribute, we punt it to the lightmap path and hope for the best,
6727                 // but lighting doesn't work.
6728                 //
6729                 // FIXME: this is fine for effects but CSQC polygons should be subject
6730                 // to lighting.
6731                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
6732                 for (q = 0; q < 3; q++)
6733                 {
6734                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
6735                         t->render_modellight_lightdir[q] = q == 2;
6736                         t->render_modellight_ambient[q] = 0;
6737                         t->render_modellight_diffuse[q] = 0;
6738                         t->render_modellight_specular[q] = 0;
6739                         t->render_lightmap_ambient[q] = 0;
6740                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
6741                         t->render_lightmap_specular[q] = 0;
6742                         t->render_rtlight_diffuse[q] = 0;
6743                         t->render_rtlight_specular[q] = 0;
6744                 }
6745         }
6746
6747         for (q = 0; q < 3; q++)
6748         {
6749                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
6750                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
6751         }
6752
6753         if (rsurface.ent_flags & RENDER_ADDITIVE)
6754                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6755         else if (t->currentalpha < 1)
6756                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6757         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
6758         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6759                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
6760         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6761                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6762         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6763                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6764         if (t->backgroundshaderpass)
6765                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6766         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6767         {
6768                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
6769                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6770         }
6771         else
6772                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
6773         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
6774         {
6775                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
6776                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
6777         }
6778         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6779                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6780
6781         // there is no tcmod
6782         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6783         {
6784                 t->currenttexmatrix = r_waterscrollmatrix;
6785                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6786         }
6787         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6788         {
6789                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6790                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6791         }
6792
6793         if (t->materialshaderpass)
6794                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6795                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6796
6797         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
6798         if (t->currentskinframe->qpixels)
6799                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6800         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6801         if (!t->basetexture)
6802                 t->basetexture = r_texture_notexture;
6803         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6804         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6805         t->nmaptexture = t->currentskinframe->nmap;
6806         if (!t->nmaptexture)
6807                 t->nmaptexture = r_texture_blanknormalmap;
6808         t->glosstexture = r_texture_black;
6809         t->glowtexture = t->currentskinframe->glow;
6810         t->fogtexture = t->currentskinframe->fog;
6811         t->reflectmasktexture = t->currentskinframe->reflect;
6812         if (t->backgroundshaderpass)
6813         {
6814                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
6815                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6816                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6817                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6818                 t->backgroundglosstexture = r_texture_black;
6819                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6820                 if (!t->backgroundnmaptexture)
6821                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6822                 // make sure that if glow is going to be used, both textures are not NULL
6823                 if (!t->backgroundglowtexture && t->glowtexture)
6824                         t->backgroundglowtexture = r_texture_black;
6825                 if (!t->glowtexture && t->backgroundglowtexture)
6826                         t->glowtexture = r_texture_black;
6827         }
6828         else
6829         {
6830                 t->backgroundbasetexture = r_texture_white;
6831                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6832                 t->backgroundglosstexture = r_texture_black;
6833                 t->backgroundglowtexture = NULL;
6834         }
6835         t->specularpower = r_shadow_glossexponent.value;
6836         // TODO: store reference values for these in the texture?
6837         if (r_shadow_gloss.integer > 0)
6838         {
6839                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6840                 {
6841                         if (r_shadow_glossintensity.value > 0)
6842                         {
6843                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6844                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6845                                 specularscale = r_shadow_glossintensity.value;
6846                         }
6847                 }
6848                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6849                 {
6850                         t->glosstexture = r_texture_white;
6851                         t->backgroundglosstexture = r_texture_white;
6852                         specularscale = r_shadow_gloss2intensity.value;
6853                         t->specularpower = r_shadow_gloss2exponent.value;
6854                 }
6855         }
6856         specularscale *= t->specularscalemod;
6857         t->specularpower *= t->specularpowermod;
6858
6859         // lightmaps mode looks bad with dlights using actual texturing, so turn
6860         // off the colormap and glossmap, but leave the normalmap on as it still
6861         // accurately represents the shading involved
6862         if (gl_lightmaps.integer)
6863         {
6864                 t->basetexture = r_texture_grey128;
6865                 t->pantstexture = r_texture_black;
6866                 t->shirttexture = r_texture_black;
6867                 if (gl_lightmaps.integer < 2)
6868                         t->nmaptexture = r_texture_blanknormalmap;
6869                 t->glosstexture = r_texture_black;
6870                 t->glowtexture = NULL;
6871                 t->fogtexture = NULL;
6872                 t->reflectmasktexture = NULL;
6873                 t->backgroundbasetexture = NULL;
6874                 if (gl_lightmaps.integer < 2)
6875                         t->backgroundnmaptexture = r_texture_blanknormalmap;
6876                 t->backgroundglosstexture = r_texture_black;
6877                 t->backgroundglowtexture = NULL;
6878                 specularscale = 0;
6879                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6880         }
6881
6882         if (specularscale != 1.0f)
6883         {
6884                 for (q = 0; q < 3; q++)
6885                 {
6886                         t->render_modellight_specular[q] *= specularscale;
6887                         t->render_lightmap_specular[q] *= specularscale;
6888                         t->render_rtlight_specular[q] *= specularscale;
6889                 }
6890         }
6891
6892         t->currentnumlayers = 0;
6893         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6894         {
6895                 int blendfunc1, blendfunc2;
6896                 qboolean depthmask;
6897                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6898                 {
6899                         blendfunc1 = GL_SRC_ALPHA;
6900                         blendfunc2 = GL_ONE;
6901                 }
6902                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6903                 {
6904                         blendfunc1 = GL_SRC_ALPHA;
6905                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6906                 }
6907                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6908                 {
6909                         blendfunc1 = t->customblendfunc[0];
6910                         blendfunc2 = t->customblendfunc[1];
6911                 }
6912                 else
6913                 {
6914                         blendfunc1 = GL_ONE;
6915                         blendfunc2 = GL_ZERO;
6916                 }
6917                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6918                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6919                 {
6920                         // basic lit geometry
6921                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
6922                         // add pants/shirt if needed
6923                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
6924                                 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);
6925                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
6926                                 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);
6927                 }
6928                 else
6929                 {
6930                         // basic lit geometry
6931                         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);
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, 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);
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, 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);
6937                         // now add ambient passes if needed
6938                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
6939                         {
6940                                 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);
6941                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
6942                                         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);
6943                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
6944                                         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);
6945                         }
6946                 }
6947                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
6948                         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);
6949                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6950                 {
6951                         // if this is opaque use alpha blend which will darken the earlier
6952                         // passes cheaply.
6953                         //
6954                         // if this is an alpha blended material, all the earlier passes
6955                         // were darkened by fog already, so we only need to add the fog
6956                         // color ontop through the fog mask texture
6957                         //
6958                         // if this is an additive blended material, all the earlier passes
6959                         // were darkened by fog already, and we should not add fog color
6960                         // (because the background was not darkened, there is no fog color
6961                         // that was lost behind it).
6962                         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);
6963                 }
6964         }
6965
6966         return t;
6967 }
6968
6969 rsurfacestate_t rsurface;
6970
6971 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6972 {
6973         dp_model_t *model = ent->model;
6974         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6975         //      return;
6976         rsurface.entity = (entity_render_t *)ent;
6977         rsurface.skeleton = ent->skeleton;
6978         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
6979         rsurface.ent_skinnum = ent->skinnum;
6980         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;
6981         rsurface.ent_flags = ent->flags;
6982         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
6983                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
6984         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
6985         rsurface.matrix = ent->matrix;
6986         rsurface.inversematrix = ent->inversematrix;
6987         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6988         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6989         R_EntityMatrix(&rsurface.matrix);
6990         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6991         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6992         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
6993         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6994         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6995         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6996         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6997         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6998         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6999         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7000         if (ent->model->brush.submodel && !prepass)
7001         {
7002                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7003                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7004         }
7005         // if the animcache code decided it should use the shader path, skip the deform step
7006         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
7007         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
7008         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
7009         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
7010         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
7011         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
7012         {
7013                 if (ent->animcache_vertex3f)
7014                 {
7015                         r_refdef.stats[r_stat_batch_entitycache_count]++;
7016                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
7017                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
7018                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
7019                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7020                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
7021                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
7022                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7023                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
7024                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
7025                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7026                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
7027                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
7028                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7029                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
7030                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
7031                 }
7032                 else if (wanttangents)
7033                 {
7034                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7035                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7036                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7037                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7038                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7039                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7040                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7041                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7042                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7043                         rsurface.modelvertex3f_vertexbuffer = NULL;
7044                         rsurface.modelvertex3f_bufferoffset = 0;
7045                         rsurface.modelvertex3f_vertexbuffer = 0;
7046                         rsurface.modelvertex3f_bufferoffset = 0;
7047                         rsurface.modelsvector3f_vertexbuffer = 0;
7048                         rsurface.modelsvector3f_bufferoffset = 0;
7049                         rsurface.modeltvector3f_vertexbuffer = 0;
7050                         rsurface.modeltvector3f_bufferoffset = 0;
7051                         rsurface.modelnormal3f_vertexbuffer = 0;
7052                         rsurface.modelnormal3f_bufferoffset = 0;
7053                 }
7054                 else if (wantnormals)
7055                 {
7056                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7057                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7058                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7059                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7060                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7061                         rsurface.modelsvector3f = NULL;
7062                         rsurface.modeltvector3f = NULL;
7063                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7064                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7065                         rsurface.modelvertex3f_vertexbuffer = NULL;
7066                         rsurface.modelvertex3f_bufferoffset = 0;
7067                         rsurface.modelvertex3f_vertexbuffer = 0;
7068                         rsurface.modelvertex3f_bufferoffset = 0;
7069                         rsurface.modelsvector3f_vertexbuffer = 0;
7070                         rsurface.modelsvector3f_bufferoffset = 0;
7071                         rsurface.modeltvector3f_vertexbuffer = 0;
7072                         rsurface.modeltvector3f_bufferoffset = 0;
7073                         rsurface.modelnormal3f_vertexbuffer = 0;
7074                         rsurface.modelnormal3f_bufferoffset = 0;
7075                 }
7076                 else
7077                 {
7078                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
7079                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
7080                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
7081                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
7082                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7083                         rsurface.modelsvector3f = NULL;
7084                         rsurface.modeltvector3f = NULL;
7085                         rsurface.modelnormal3f = NULL;
7086                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7087                         rsurface.modelvertex3f_vertexbuffer = NULL;
7088                         rsurface.modelvertex3f_bufferoffset = 0;
7089                         rsurface.modelvertex3f_vertexbuffer = 0;
7090                         rsurface.modelvertex3f_bufferoffset = 0;
7091                         rsurface.modelsvector3f_vertexbuffer = 0;
7092                         rsurface.modelsvector3f_bufferoffset = 0;
7093                         rsurface.modeltvector3f_vertexbuffer = 0;
7094                         rsurface.modeltvector3f_bufferoffset = 0;
7095                         rsurface.modelnormal3f_vertexbuffer = 0;
7096                         rsurface.modelnormal3f_bufferoffset = 0;
7097                 }
7098                 rsurface.modelgeneratedvertex = true;
7099         }
7100         else
7101         {
7102                 if (rsurface.entityskeletaltransform3x4)
7103                 {
7104                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
7105                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
7106                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
7107                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
7108                 }
7109                 else
7110                 {
7111                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
7112                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
7113                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
7114                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
7115                 }
7116                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7117                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.data_vertex3f_vertexbuffer;
7118                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.data_vertex3f_bufferoffset;
7119                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7120                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.data_svector3f_vertexbuffer;
7121                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.data_svector3f_bufferoffset;
7122                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7123                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.data_tvector3f_vertexbuffer;
7124                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.data_tvector3f_bufferoffset;
7125                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7126                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.data_normal3f_vertexbuffer;
7127                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.data_normal3f_bufferoffset;
7128                 rsurface.modelgeneratedvertex = false;
7129         }
7130         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7131         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.data_lightmapcolor4f_vertexbuffer;
7132         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.data_lightmapcolor4f_bufferoffset;
7133         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7134         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.data_texcoordtexture2f_vertexbuffer;
7135         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.data_texcoordtexture2f_bufferoffset;
7136         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7137         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.data_texcoordlightmap2f_vertexbuffer;
7138         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.data_texcoordlightmap2f_bufferoffset;
7139         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
7140         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.data_skeletalindex4ub_vertexbuffer;
7141         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.data_skeletalindex4ub_bufferoffset;
7142         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
7143         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.data_skeletalweight4ub_vertexbuffer;
7144         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.data_skeletalweight4ub_bufferoffset;
7145         rsurface.modelelement3i = model->surfmesh.data_element3i;
7146         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7147         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7148         rsurface.modelelement3s = model->surfmesh.data_element3s;
7149         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7150         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7151         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7152         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7153         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7154         rsurface.modelsurfaces = model->data_surfaces;
7155         rsurface.batchgeneratedvertex = false;
7156         rsurface.batchfirstvertex = 0;
7157         rsurface.batchnumvertices = 0;
7158         rsurface.batchfirsttriangle = 0;
7159         rsurface.batchnumtriangles = 0;
7160         rsurface.batchvertex3f  = NULL;
7161         rsurface.batchvertex3f_vertexbuffer = NULL;
7162         rsurface.batchvertex3f_bufferoffset = 0;
7163         rsurface.batchsvector3f = NULL;
7164         rsurface.batchsvector3f_vertexbuffer = NULL;
7165         rsurface.batchsvector3f_bufferoffset = 0;
7166         rsurface.batchtvector3f = NULL;
7167         rsurface.batchtvector3f_vertexbuffer = NULL;
7168         rsurface.batchtvector3f_bufferoffset = 0;
7169         rsurface.batchnormal3f  = NULL;
7170         rsurface.batchnormal3f_vertexbuffer = NULL;
7171         rsurface.batchnormal3f_bufferoffset = 0;
7172         rsurface.batchlightmapcolor4f = NULL;
7173         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7174         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7175         rsurface.batchtexcoordtexture2f = NULL;
7176         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7177         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7178         rsurface.batchtexcoordlightmap2f = NULL;
7179         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7180         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7181         rsurface.batchskeletalindex4ub = NULL;
7182         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7183         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7184         rsurface.batchskeletalweight4ub = NULL;
7185         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7186         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7187         rsurface.batchelement3i = NULL;
7188         rsurface.batchelement3i_indexbuffer = NULL;
7189         rsurface.batchelement3i_bufferoffset = 0;
7190         rsurface.batchelement3s = NULL;
7191         rsurface.batchelement3s_indexbuffer = NULL;
7192         rsurface.batchelement3s_bufferoffset = 0;
7193         rsurface.forcecurrenttextureupdate = false;
7194 }
7195
7196 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)
7197 {
7198         rsurface.entity = r_refdef.scene.worldentity;
7199         rsurface.skeleton = NULL;
7200         rsurface.ent_skinnum = 0;
7201         rsurface.ent_qwskin = -1;
7202         rsurface.ent_flags = entflags;
7203         rsurface.shadertime = r_refdef.scene.time - shadertime;
7204         rsurface.modelnumvertices = numvertices;
7205         rsurface.modelnumtriangles = numtriangles;
7206         rsurface.matrix = *matrix;
7207         rsurface.inversematrix = *inversematrix;
7208         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7209         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7210         R_EntityMatrix(&rsurface.matrix);
7211         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7212         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7213         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7214         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7215         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7216         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7217         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7218         rsurface.frameblend[0].lerp = 1;
7219         rsurface.ent_alttextures = false;
7220         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7221         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7222         rsurface.entityskeletaltransform3x4 = NULL;
7223         rsurface.entityskeletaltransform3x4buffer = NULL;
7224         rsurface.entityskeletaltransform3x4offset = 0;
7225         rsurface.entityskeletaltransform3x4size = 0;
7226         rsurface.entityskeletalnumtransforms = 0;
7227         r_refdef.stats[r_stat_batch_entitycustom_count]++;
7228         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
7229         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
7230         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
7231         if (wanttangents)
7232         {
7233                 rsurface.modelvertex3f = (float *)vertex3f;
7234                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7235                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7236                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7237         }
7238         else if (wantnormals)
7239         {
7240                 rsurface.modelvertex3f = (float *)vertex3f;
7241                 rsurface.modelsvector3f = NULL;
7242                 rsurface.modeltvector3f = NULL;
7243                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7244         }
7245         else
7246         {
7247                 rsurface.modelvertex3f = (float *)vertex3f;
7248                 rsurface.modelsvector3f = NULL;
7249                 rsurface.modeltvector3f = NULL;
7250                 rsurface.modelnormal3f = NULL;
7251         }
7252         rsurface.modelvertex3f_vertexbuffer = 0;
7253         rsurface.modelvertex3f_bufferoffset = 0;
7254         rsurface.modelsvector3f_vertexbuffer = 0;
7255         rsurface.modelsvector3f_bufferoffset = 0;
7256         rsurface.modeltvector3f_vertexbuffer = 0;
7257         rsurface.modeltvector3f_bufferoffset = 0;
7258         rsurface.modelnormal3f_vertexbuffer = 0;
7259         rsurface.modelnormal3f_bufferoffset = 0;
7260         rsurface.modelgeneratedvertex = true;
7261         rsurface.modellightmapcolor4f  = (float *)color4f;
7262         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7263         rsurface.modellightmapcolor4f_bufferoffset = 0;
7264         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7265         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7266         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7267         rsurface.modeltexcoordlightmap2f  = NULL;
7268         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7269         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7270         rsurface.modelskeletalindex4ub = NULL;
7271         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
7272         rsurface.modelskeletalindex4ub_bufferoffset = 0;
7273         rsurface.modelskeletalweight4ub = NULL;
7274         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
7275         rsurface.modelskeletalweight4ub_bufferoffset = 0;
7276         rsurface.modelelement3i = (int *)element3i;
7277         rsurface.modelelement3i_indexbuffer = NULL;
7278         rsurface.modelelement3i_bufferoffset = 0;
7279         rsurface.modelelement3s = (unsigned short *)element3s;
7280         rsurface.modelelement3s_indexbuffer = NULL;
7281         rsurface.modelelement3s_bufferoffset = 0;
7282         rsurface.modellightmapoffsets = NULL;
7283         rsurface.modelsurfaces = NULL;
7284         rsurface.batchgeneratedvertex = false;
7285         rsurface.batchfirstvertex = 0;
7286         rsurface.batchnumvertices = 0;
7287         rsurface.batchfirsttriangle = 0;
7288         rsurface.batchnumtriangles = 0;
7289         rsurface.batchvertex3f  = NULL;
7290         rsurface.batchvertex3f_vertexbuffer = NULL;
7291         rsurface.batchvertex3f_bufferoffset = 0;
7292         rsurface.batchsvector3f = NULL;
7293         rsurface.batchsvector3f_vertexbuffer = NULL;
7294         rsurface.batchsvector3f_bufferoffset = 0;
7295         rsurface.batchtvector3f = NULL;
7296         rsurface.batchtvector3f_vertexbuffer = NULL;
7297         rsurface.batchtvector3f_bufferoffset = 0;
7298         rsurface.batchnormal3f  = NULL;
7299         rsurface.batchnormal3f_vertexbuffer = NULL;
7300         rsurface.batchnormal3f_bufferoffset = 0;
7301         rsurface.batchlightmapcolor4f = NULL;
7302         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7303         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7304         rsurface.batchtexcoordtexture2f = NULL;
7305         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7306         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7307         rsurface.batchtexcoordlightmap2f = NULL;
7308         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7309         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7310         rsurface.batchskeletalindex4ub = NULL;
7311         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7312         rsurface.batchskeletalindex4ub_bufferoffset = 0;
7313         rsurface.batchskeletalweight4ub = NULL;
7314         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7315         rsurface.batchskeletalweight4ub_bufferoffset = 0;
7316         rsurface.batchelement3i = NULL;
7317         rsurface.batchelement3i_indexbuffer = NULL;
7318         rsurface.batchelement3i_bufferoffset = 0;
7319         rsurface.batchelement3s = NULL;
7320         rsurface.batchelement3s_indexbuffer = NULL;
7321         rsurface.batchelement3s_bufferoffset = 0;
7322         rsurface.forcecurrenttextureupdate = true;
7323
7324         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7325         {
7326                 if ((wantnormals || wanttangents) && !normal3f)
7327                 {
7328                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7329                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7330                 }
7331                 if (wanttangents && !svector3f)
7332                 {
7333                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7334                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7335                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7336                 }
7337         }
7338 }
7339
7340 float RSurf_FogPoint(const float *v)
7341 {
7342         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7343         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7344         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7345         float FogHeightFade = r_refdef.fogheightfade;
7346         float fogfrac;
7347         unsigned int fogmasktableindex;
7348         if (r_refdef.fogplaneviewabove)
7349                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7350         else
7351                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7352         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7353         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7354 }
7355
7356 float RSurf_FogVertex(const float *v)
7357 {
7358         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7359         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7360         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7361         float FogHeightFade = rsurface.fogheightfade;
7362         float fogfrac;
7363         unsigned int fogmasktableindex;
7364         if (r_refdef.fogplaneviewabove)
7365                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7366         else
7367                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7368         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7369         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7370 }
7371
7372 void RSurf_UploadBuffersForBatch(void)
7373 {
7374         // 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)
7375         // note that if rsurface.batchvertex3f_vertexbuffer is NULL, dynamicvertex is forced as we don't account for the proper base vertex here.
7376         if (rsurface.batchvertex3f && !rsurface.batchvertex3f_vertexbuffer)
7377                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
7378         if (rsurface.batchsvector3f && !rsurface.batchsvector3f_vertexbuffer)
7379                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
7380         if (rsurface.batchtvector3f && !rsurface.batchtvector3f_vertexbuffer)
7381                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
7382         if (rsurface.batchnormal3f && !rsurface.batchnormal3f_vertexbuffer)
7383                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
7384         if (rsurface.batchlightmapcolor4f && !rsurface.batchlightmapcolor4f_vertexbuffer)
7385                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
7386         if (rsurface.batchtexcoordtexture2f && !rsurface.batchtexcoordtexture2f_vertexbuffer)
7387                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
7388         if (rsurface.batchtexcoordlightmap2f && !rsurface.batchtexcoordlightmap2f_vertexbuffer)
7389                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
7390         if (rsurface.batchskeletalindex4ub && !rsurface.batchskeletalindex4ub_vertexbuffer)
7391                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
7392         if (rsurface.batchskeletalweight4ub && !rsurface.batchskeletalweight4ub_vertexbuffer)
7393                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
7394
7395         if (rsurface.batchelement3s && !rsurface.batchelement3s_indexbuffer)
7396                 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
7397         else if (rsurface.batchelement3i && !rsurface.batchelement3i_indexbuffer)
7398                 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
7399
7400         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7401         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7402         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7403         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7404         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7405         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7406         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7407         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
7408         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
7409         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
7410 }
7411
7412 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7413 {
7414         int i;
7415         for (i = 0;i < numelements;i++)
7416                 outelement3i[i] = inelement3i[i] + adjust;
7417 }
7418
7419 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7420 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7421 {
7422         int deformindex;
7423         int firsttriangle;
7424         int numtriangles;
7425         int firstvertex;
7426         int endvertex;
7427         int numvertices;
7428         int surfacefirsttriangle;
7429         int surfacenumtriangles;
7430         int surfacefirstvertex;
7431         int surfaceendvertex;
7432         int surfacenumvertices;
7433         int batchnumsurfaces = texturenumsurfaces;
7434         int batchnumvertices;
7435         int batchnumtriangles;
7436         int i, j;
7437         qboolean gaps;
7438         qboolean dynamicvertex;
7439         float amplitude;
7440         float animpos;
7441         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7442         float waveparms[4];
7443         unsigned char *ub;
7444         q3shaderinfo_deform_t *deform;
7445         const msurface_t *surface, *firstsurface;
7446         if (!texturenumsurfaces)
7447                 return;
7448         // find vertex range of this surface batch
7449         gaps = false;
7450         firstsurface = texturesurfacelist[0];
7451         firsttriangle = firstsurface->num_firsttriangle;
7452         batchnumvertices = 0;
7453         batchnumtriangles = 0;
7454         firstvertex = endvertex = firstsurface->num_firstvertex;
7455         for (i = 0;i < texturenumsurfaces;i++)
7456         {
7457                 surface = texturesurfacelist[i];
7458                 if (surface != firstsurface + i)
7459                         gaps = true;
7460                 surfacefirstvertex = surface->num_firstvertex;
7461                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
7462                 surfacenumvertices = surface->num_vertices;
7463                 surfacenumtriangles = surface->num_triangles;
7464                 if (firstvertex > surfacefirstvertex)
7465                         firstvertex = surfacefirstvertex;
7466                 if (endvertex < surfaceendvertex)
7467                         endvertex = surfaceendvertex;
7468                 batchnumvertices += surfacenumvertices;
7469                 batchnumtriangles += surfacenumtriangles;
7470         }
7471
7472         r_refdef.stats[r_stat_batch_batches]++;
7473         if (gaps)
7474                 r_refdef.stats[r_stat_batch_withgaps]++;
7475         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
7476         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
7477         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
7478
7479         // we now know the vertex range used, and if there are any gaps in it
7480         rsurface.batchfirstvertex = firstvertex;
7481         rsurface.batchnumvertices = endvertex - firstvertex;
7482         rsurface.batchfirsttriangle = firsttriangle;
7483         rsurface.batchnumtriangles = batchnumtriangles;
7484
7485         // check if any dynamic vertex processing must occur
7486         dynamicvertex = false;
7487
7488         // we must use vertexbuffers for rendering, we can upload vertex buffers
7489         // easily enough but if the basevertex is non-zero it becomes more
7490         // difficult, so force dynamicvertex path in that case - it's suboptimal
7491         // but the most optimal case is to have the geometry sources provide their
7492         // own anyway.
7493         if (!rsurface.modelvertex3f_vertexbuffer && firstvertex != 0)
7494                 dynamicvertex = true;
7495
7496         // a cvar to force the dynamic vertex path to be taken, for debugging
7497         if (r_batch_debugdynamicvertexpath.integer)
7498         {
7499                 if (!dynamicvertex)
7500                 {
7501                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
7502                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
7503                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
7504                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
7505                 }
7506                 dynamicvertex = true;
7507         }
7508
7509         // if there is a chance of animated vertex colors, it's a dynamic batch
7510         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
7511         {
7512                 if (!dynamicvertex)
7513                 {
7514                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
7515                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
7516                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
7517                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
7518                 }
7519                 dynamicvertex = true;
7520         }
7521
7522         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
7523         {
7524                 switch (deform->deform)
7525                 {
7526                 default:
7527                 case Q3DEFORM_PROJECTIONSHADOW:
7528                 case Q3DEFORM_TEXT0:
7529                 case Q3DEFORM_TEXT1:
7530                 case Q3DEFORM_TEXT2:
7531                 case Q3DEFORM_TEXT3:
7532                 case Q3DEFORM_TEXT4:
7533                 case Q3DEFORM_TEXT5:
7534                 case Q3DEFORM_TEXT6:
7535                 case Q3DEFORM_TEXT7:
7536                 case Q3DEFORM_NONE:
7537                         break;
7538                 case Q3DEFORM_AUTOSPRITE:
7539                         if (!dynamicvertex)
7540                         {
7541                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
7542                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
7543                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
7544                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
7545                         }
7546                         dynamicvertex = true;
7547                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
7548                         break;
7549                 case Q3DEFORM_AUTOSPRITE2:
7550                         if (!dynamicvertex)
7551                         {
7552                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
7553                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
7554                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
7555                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
7556                         }
7557                         dynamicvertex = true;
7558                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7559                         break;
7560                 case Q3DEFORM_NORMAL:
7561                         if (!dynamicvertex)
7562                         {
7563                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
7564                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
7565                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
7566                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
7567                         }
7568                         dynamicvertex = true;
7569                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7570                         break;
7571                 case Q3DEFORM_WAVE:
7572                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7573                                 break; // if wavefunc is a nop, ignore this transform
7574                         if (!dynamicvertex)
7575                         {
7576                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
7577                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
7578                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
7579                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
7580                         }
7581                         dynamicvertex = true;
7582                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7583                         break;
7584                 case Q3DEFORM_BULGE:
7585                         if (!dynamicvertex)
7586                         {
7587                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
7588                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
7589                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
7590                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
7591                         }
7592                         dynamicvertex = true;
7593                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
7594                         break;
7595                 case Q3DEFORM_MOVE:
7596                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
7597                                 break; // if wavefunc is a nop, ignore this transform
7598                         if (!dynamicvertex)
7599                         {
7600                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
7601                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
7602                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
7603                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
7604                         }
7605                         dynamicvertex = true;
7606                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7607                         break;
7608                 }
7609         }
7610         if (rsurface.texture->materialshaderpass)
7611         {
7612                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
7613                 {
7614                 default:
7615                 case Q3TCGEN_TEXTURE:
7616                         break;
7617                 case Q3TCGEN_LIGHTMAP:
7618                         if (!dynamicvertex)
7619                         {
7620                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
7621                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
7622                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
7623                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
7624                         }
7625                         dynamicvertex = true;
7626                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
7627                         break;
7628                 case Q3TCGEN_VECTOR:
7629                         if (!dynamicvertex)
7630                         {
7631                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
7632                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
7633                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
7634                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
7635                         }
7636                         dynamicvertex = true;
7637                         batchneed |= BATCHNEED_ARRAY_VERTEX;
7638                         break;
7639                 case Q3TCGEN_ENVIRONMENT:
7640                         if (!dynamicvertex)
7641                         {
7642                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
7643                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
7644                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
7645                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
7646                         }
7647                         dynamicvertex = true;
7648                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
7649                         break;
7650                 }
7651                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7652                 {
7653                         if (!dynamicvertex)
7654                         {
7655                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
7656                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
7657                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
7658                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
7659                         }
7660                         dynamicvertex = true;
7661                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
7662                 }
7663         }
7664
7665         // the caller can specify BATCHNEED_NOGAPS to force a batch with
7666         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
7667         // we ensure this by treating the vertex batch as dynamic...
7668         if ((batchneed & BATCHNEED_ALWAYSCOPY) || ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0)))
7669         {
7670                 if (!dynamicvertex)
7671                 {
7672                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
7673                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
7674                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
7675                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
7676                 }
7677                 dynamicvertex = true;
7678         }
7679
7680         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
7681         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
7682                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
7683
7684         rsurface.batchvertex3f = rsurface.modelvertex3f;
7685         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
7686         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7687         rsurface.batchsvector3f = rsurface.modelsvector3f;
7688         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
7689         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7690         rsurface.batchtvector3f = rsurface.modeltvector3f;
7691         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
7692         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7693         rsurface.batchnormal3f = rsurface.modelnormal3f;
7694         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
7695         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7696         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
7697         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
7698         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
7699         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
7700         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
7701         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7702         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7703         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
7704         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7705         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
7706         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
7707         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
7708         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
7709         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
7710         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
7711         rsurface.batchelement3i = rsurface.modelelement3i;
7712         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
7713         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
7714         rsurface.batchelement3s = rsurface.modelelement3s;
7715         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
7716         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
7717         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
7718         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
7719         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
7720         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
7721         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
7722
7723         // if any dynamic vertex processing has to occur in software, we copy the
7724         // entire surface list together before processing to rebase the vertices
7725         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
7726         //
7727         // if any gaps exist and we do not have a static vertex buffer, we have to
7728         // copy the surface list together to avoid wasting upload bandwidth on the
7729         // vertices in the gaps.
7730         //
7731         // if gaps exist and we have a static vertex buffer, we can choose whether
7732         // to combine the index buffer ranges into one dynamic index buffer or
7733         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
7734         //
7735         // in many cases the batch is reduced to one draw call.
7736
7737         rsurface.batchmultidraw = false;
7738         rsurface.batchmultidrawnumsurfaces = 0;
7739         rsurface.batchmultidrawsurfacelist = NULL;
7740
7741         if (!dynamicvertex)
7742         {
7743                 // static vertex data, just set pointers...
7744                 rsurface.batchgeneratedvertex = false;
7745                 // if there are gaps, we want to build a combined index buffer,
7746                 // otherwise use the original static buffer with an appropriate offset
7747                 if (gaps)
7748                 {
7749                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
7750                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
7751                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
7752                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
7753                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
7754                         {
7755                                 rsurface.batchmultidraw = true;
7756                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
7757                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
7758                                 return;
7759                         }
7760                         // build a new triangle elements array for this batch
7761                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7762                         rsurface.batchfirsttriangle = 0;
7763                         numtriangles = 0;
7764                         for (i = 0;i < texturenumsurfaces;i++)
7765                         {
7766                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7767                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7768                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
7769                                 numtriangles += surfacenumtriangles;
7770                         }
7771                         rsurface.batchelement3i_indexbuffer = NULL;
7772                         rsurface.batchelement3i_bufferoffset = 0;
7773                         rsurface.batchelement3s = NULL;
7774                         rsurface.batchelement3s_indexbuffer = NULL;
7775                         rsurface.batchelement3s_bufferoffset = 0;
7776                         if (endvertex <= 65536)
7777                         {
7778                                 // make a 16bit (unsigned short) index array if possible
7779                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7780                                 for (i = 0;i < numtriangles*3;i++)
7781                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7782                         }
7783                 }
7784                 else
7785                 {
7786                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
7787                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
7788                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
7789                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
7790                 }
7791                 return;
7792         }
7793
7794         // something needs software processing, do it for real...
7795         // we only directly handle separate array data in this case and then
7796         // generate interleaved data if needed...
7797         rsurface.batchgeneratedvertex = true;
7798         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
7799         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
7800         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
7801         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
7802
7803         // now copy the vertex data into a combined array and make an index array
7804         // (this is what Quake3 does all the time)
7805         // we also apply any skeletal animation here that would have been done in
7806         // the vertex shader, because most of the dynamic vertex animation cases
7807         // need actual vertex positions and normals
7808         //if (dynamicvertex)
7809         {
7810                 rsurface.batchvertex3f = NULL;
7811                 rsurface.batchvertex3f_vertexbuffer = NULL;
7812                 rsurface.batchvertex3f_bufferoffset = 0;
7813                 rsurface.batchsvector3f = NULL;
7814                 rsurface.batchsvector3f_vertexbuffer = NULL;
7815                 rsurface.batchsvector3f_bufferoffset = 0;
7816                 rsurface.batchtvector3f = NULL;
7817                 rsurface.batchtvector3f_vertexbuffer = NULL;
7818                 rsurface.batchtvector3f_bufferoffset = 0;
7819                 rsurface.batchnormal3f = NULL;
7820                 rsurface.batchnormal3f_vertexbuffer = NULL;
7821                 rsurface.batchnormal3f_bufferoffset = 0;
7822                 rsurface.batchlightmapcolor4f = NULL;
7823                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7824                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7825                 rsurface.batchtexcoordtexture2f = NULL;
7826                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7827                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7828                 rsurface.batchtexcoordlightmap2f = NULL;
7829                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7830                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7831                 rsurface.batchskeletalindex4ub = NULL;
7832                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
7833                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
7834                 rsurface.batchskeletalweight4ub = NULL;
7835                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
7836                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
7837                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
7838                 rsurface.batchelement3i_indexbuffer = NULL;
7839                 rsurface.batchelement3i_bufferoffset = 0;
7840                 rsurface.batchelement3s = NULL;
7841                 rsurface.batchelement3s_indexbuffer = NULL;
7842                 rsurface.batchelement3s_bufferoffset = 0;
7843                 rsurface.batchskeletaltransform3x4buffer = NULL;
7844                 rsurface.batchskeletaltransform3x4offset = 0;
7845                 rsurface.batchskeletaltransform3x4size = 0;
7846                 // we'll only be setting up certain arrays as needed
7847                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7848                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7849                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7850                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7851                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7852                 {
7853                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7854                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
7855                 }
7856                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7857                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
7858                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7859                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7860                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7861                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
7862                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7863                 {
7864                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7865                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
7866                 }
7867                 numvertices = 0;
7868                 numtriangles = 0;
7869                 for (i = 0;i < texturenumsurfaces;i++)
7870                 {
7871                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
7872                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
7873                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
7874                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
7875                         // copy only the data requested
7876                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
7877                         {
7878                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
7879                                 {
7880                                         if (rsurface.batchvertex3f)
7881                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7882                                         else
7883                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7884                                 }
7885                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
7886                                 {
7887                                         if (rsurface.modelnormal3f)
7888                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7889                                         else
7890                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7891                                 }
7892                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
7893                                 {
7894                                         if (rsurface.modelsvector3f)
7895                                         {
7896                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7897                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
7898                                         }
7899                                         else
7900                                         {
7901                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7902                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
7903                                         }
7904                                 }
7905                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
7906                                 {
7907                                         if (rsurface.modellightmapcolor4f)
7908                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
7909                                         else
7910                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
7911                                 }
7912                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
7913                                 {
7914                                         if (rsurface.modeltexcoordtexture2f)
7915                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7916                                         else
7917                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7918                                 }
7919                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
7920                                 {
7921                                         if (rsurface.modeltexcoordlightmap2f)
7922                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
7923                                         else
7924                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
7925                                 }
7926                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
7927                                 {
7928                                         if (rsurface.modelskeletalindex4ub)
7929                                         {
7930                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7931                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
7932                                         }
7933                                         else
7934                                         {
7935                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7936                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
7937                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
7938                                                 for (j = 0;j < surfacenumvertices;j++)
7939                                                         ub[j*4] = 255;
7940                                         }
7941                                 }
7942                         }
7943                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
7944                         numvertices += surfacenumvertices;
7945                         numtriangles += surfacenumtriangles;
7946                 }
7947
7948                 // generate a 16bit index array as well if possible
7949                 // (in general, dynamic batches fit)
7950                 if (numvertices <= 65536)
7951                 {
7952                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
7953                         for (i = 0;i < numtriangles*3;i++)
7954                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
7955                 }
7956
7957                 // since we've copied everything, the batch now starts at 0
7958                 rsurface.batchfirstvertex = 0;
7959                 rsurface.batchnumvertices = batchnumvertices;
7960                 rsurface.batchfirsttriangle = 0;
7961                 rsurface.batchnumtriangles = batchnumtriangles;
7962         }
7963
7964         // apply skeletal animation that would have been done in the vertex shader
7965         if (rsurface.batchskeletaltransform3x4)
7966         {
7967                 const unsigned char *si;
7968                 const unsigned char *sw;
7969                 const float *t[4];
7970                 const float *b = rsurface.batchskeletaltransform3x4;
7971                 float *vp, *vs, *vt, *vn;
7972                 float w[4];
7973                 float m[3][4], n[3][4];
7974                 float tp[3], ts[3], tt[3], tn[3];
7975                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
7976                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
7977                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
7978                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
7979                 si = rsurface.batchskeletalindex4ub;
7980                 sw = rsurface.batchskeletalweight4ub;
7981                 vp = rsurface.batchvertex3f;
7982                 vs = rsurface.batchsvector3f;
7983                 vt = rsurface.batchtvector3f;
7984                 vn = rsurface.batchnormal3f;
7985                 memset(m[0], 0, sizeof(m));
7986                 memset(n[0], 0, sizeof(n));
7987                 for (i = 0;i < batchnumvertices;i++)
7988                 {
7989                         t[0] = b + si[0]*12;
7990                         if (sw[0] == 255)
7991                         {
7992                                 // common case - only one matrix
7993                                 m[0][0] = t[0][ 0];
7994                                 m[0][1] = t[0][ 1];
7995                                 m[0][2] = t[0][ 2];
7996                                 m[0][3] = t[0][ 3];
7997                                 m[1][0] = t[0][ 4];
7998                                 m[1][1] = t[0][ 5];
7999                                 m[1][2] = t[0][ 6];
8000                                 m[1][3] = t[0][ 7];
8001                                 m[2][0] = t[0][ 8];
8002                                 m[2][1] = t[0][ 9];
8003                                 m[2][2] = t[0][10];
8004                                 m[2][3] = t[0][11];
8005                         }
8006                         else if (sw[2] + sw[3])
8007                         {
8008                                 // blend 4 matrices
8009                                 t[1] = b + si[1]*12;
8010                                 t[2] = b + si[2]*12;
8011                                 t[3] = b + si[3]*12;
8012                                 w[0] = sw[0] * (1.0f / 255.0f);
8013                                 w[1] = sw[1] * (1.0f / 255.0f);
8014                                 w[2] = sw[2] * (1.0f / 255.0f);
8015                                 w[3] = sw[3] * (1.0f / 255.0f);
8016                                 // blend the matrices
8017                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
8018                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
8019                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
8020                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
8021                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
8022                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
8023                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
8024                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
8025                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
8026                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
8027                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
8028                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
8029                         }
8030                         else
8031                         {
8032                                 // blend 2 matrices
8033                                 t[1] = b + si[1]*12;
8034                                 w[0] = sw[0] * (1.0f / 255.0f);
8035                                 w[1] = sw[1] * (1.0f / 255.0f);
8036                                 // blend the matrices
8037                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
8038                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
8039                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
8040                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
8041                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
8042                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
8043                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
8044                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
8045                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
8046                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
8047                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
8048                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
8049                         }
8050                         si += 4;
8051                         sw += 4;
8052                         // modify the vertex
8053                         VectorCopy(vp, tp);
8054                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
8055                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
8056                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
8057                         vp += 3;
8058                         if (vn)
8059                         {
8060                                 // the normal transformation matrix is a set of cross products...
8061                                 CrossProduct(m[1], m[2], n[0]);
8062                                 CrossProduct(m[2], m[0], n[1]);
8063                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
8064                                 VectorCopy(vn, tn);
8065                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
8066                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
8067                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
8068                                 VectorNormalize(vn);
8069                                 vn += 3;
8070                                 if (vs)
8071                                 {
8072                                         VectorCopy(vs, ts);
8073                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
8074                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
8075                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
8076                                         VectorNormalize(vs);
8077                                         vs += 3;
8078                                         VectorCopy(vt, tt);
8079                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
8080                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
8081                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
8082                                         VectorNormalize(vt);
8083                                         vt += 3;
8084                                 }
8085                         }
8086                 }
8087                 rsurface.batchskeletaltransform3x4 = NULL;
8088                 rsurface.batchskeletalnumtransforms = 0;
8089         }
8090
8091         // q1bsp surfaces rendered in vertex color mode have to have colors
8092         // calculated based on lightstyles
8093         if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && texturesurfacelist[0]->lightmapinfo)
8094         {
8095                 // generate color arrays for the surfaces in this list
8096                 int c[4];
8097                 int scale;
8098                 int size3;
8099                 const int *offsets;
8100                 const unsigned char *lm;
8101                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8102                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8103                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8104                 numvertices = 0;
8105                 for (i = 0;i < texturenumsurfaces;i++)
8106                 {
8107                         surface = texturesurfacelist[i];
8108                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8109                         surfacenumvertices = surface->num_vertices;
8110                         if (surface->lightmapinfo->samples)
8111                         {
8112                                 for (j = 0;j < surfacenumvertices;j++)
8113                                 {
8114                                         lm = surface->lightmapinfo->samples + offsets[j];
8115                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8116                                         VectorScale(lm, scale, c);
8117                                         if (surface->lightmapinfo->styles[1] != 255)
8118                                         {
8119                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8120                                                 lm += size3;
8121                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8122                                                 VectorMA(c, scale, lm, c);
8123                                                 if (surface->lightmapinfo->styles[2] != 255)
8124                                                 {
8125                                                         lm += size3;
8126                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8127                                                         VectorMA(c, scale, lm, c);
8128                                                         if (surface->lightmapinfo->styles[3] != 255)
8129                                                         {
8130                                                                 lm += size3;
8131                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8132                                                                 VectorMA(c, scale, lm, c);
8133                                                         }
8134                                                 }
8135                                         }
8136                                         c[0] >>= 7;
8137                                         c[1] >>= 7;
8138                                         c[2] >>= 7;
8139                                         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);
8140                                         numvertices++;
8141                                 }
8142                         }
8143                         else
8144                         {
8145                                 for (j = 0;j < surfacenumvertices;j++)
8146                                 {
8147                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8148                                         numvertices++;
8149                                 }
8150                         }
8151                 }
8152         }
8153
8154         // if vertices are deformed (sprite flares and things in maps, possibly
8155         // water waves, bulges and other deformations), modify the copied vertices
8156         // in place
8157         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8158         {
8159                 float scale;
8160                 switch (deform->deform)
8161                 {
8162                 default:
8163                 case Q3DEFORM_PROJECTIONSHADOW:
8164                 case Q3DEFORM_TEXT0:
8165                 case Q3DEFORM_TEXT1:
8166                 case Q3DEFORM_TEXT2:
8167                 case Q3DEFORM_TEXT3:
8168                 case Q3DEFORM_TEXT4:
8169                 case Q3DEFORM_TEXT5:
8170                 case Q3DEFORM_TEXT6:
8171                 case Q3DEFORM_TEXT7:
8172                 case Q3DEFORM_NONE:
8173                         break;
8174                 case Q3DEFORM_AUTOSPRITE:
8175                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8176                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8177                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8178                         VectorNormalize(newforward);
8179                         VectorNormalize(newright);
8180                         VectorNormalize(newup);
8181 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8182 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8183 //                      rsurface.batchvertex3f_bufferoffset = 0;
8184 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8185 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8186 //                      rsurface.batchsvector3f_bufferoffset = 0;
8187 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8188 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8189 //                      rsurface.batchtvector3f_bufferoffset = 0;
8190 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8191 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8192 //                      rsurface.batchnormal3f_bufferoffset = 0;
8193                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8194                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8195                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8196                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8197                                 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);
8198                         // a single autosprite surface can contain multiple sprites...
8199                         for (j = 0;j < batchnumvertices - 3;j += 4)
8200                         {
8201                                 VectorClear(center);
8202                                 for (i = 0;i < 4;i++)
8203                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8204                                 VectorScale(center, 0.25f, center);
8205                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8206                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8207                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8208                                 for (i = 0;i < 4;i++)
8209                                 {
8210                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8211                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8212                                 }
8213                         }
8214                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8215                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8216                         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);
8217                         break;
8218                 case Q3DEFORM_AUTOSPRITE2:
8219                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8220                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8221                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8222                         VectorNormalize(newforward);
8223                         VectorNormalize(newright);
8224                         VectorNormalize(newup);
8225 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8226 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8227 //                      rsurface.batchvertex3f_bufferoffset = 0;
8228                         {
8229                                 const float *v1, *v2;
8230                                 vec3_t start, end;
8231                                 float f, l;
8232                                 struct
8233                                 {
8234                                         float length2;
8235                                         const float *v1;
8236                                         const float *v2;
8237                                 }
8238                                 shortest[2];
8239                                 memset(shortest, 0, sizeof(shortest));
8240                                 // a single autosprite surface can contain multiple sprites...
8241                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8242                                 {
8243                                         VectorClear(center);
8244                                         for (i = 0;i < 4;i++)
8245                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8246                                         VectorScale(center, 0.25f, center);
8247                                         // find the two shortest edges, then use them to define the
8248                                         // axis vectors for rotating around the central axis
8249                                         for (i = 0;i < 6;i++)
8250                                         {
8251                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8252                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8253                                                 l = VectorDistance2(v1, v2);
8254                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8255                                                 if (v1[2] != v2[2])
8256                                                         l += (1.0f / 1024.0f);
8257                                                 if (shortest[0].length2 > l || i == 0)
8258                                                 {
8259                                                         shortest[1] = shortest[0];
8260                                                         shortest[0].length2 = l;
8261                                                         shortest[0].v1 = v1;
8262                                                         shortest[0].v2 = v2;
8263                                                 }
8264                                                 else if (shortest[1].length2 > l || i == 1)
8265                                                 {
8266                                                         shortest[1].length2 = l;
8267                                                         shortest[1].v1 = v1;
8268                                                         shortest[1].v2 = v2;
8269                                                 }
8270                                         }
8271                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8272                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8273                                         // this calculates the right vector from the shortest edge
8274                                         // and the up vector from the edge midpoints
8275                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8276                                         VectorNormalize(right);
8277                                         VectorSubtract(end, start, up);
8278                                         VectorNormalize(up);
8279                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8280                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8281                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8282                                         VectorNegate(forward, forward);
8283                                         VectorReflect(forward, 0, up, forward);
8284                                         VectorNormalize(forward);
8285                                         CrossProduct(up, forward, newright);
8286                                         VectorNormalize(newright);
8287                                         // rotate the quad around the up axis vector, this is made
8288                                         // especially easy by the fact we know the quad is flat,
8289                                         // so we only have to subtract the center position and
8290                                         // measure distance along the right vector, and then
8291                                         // multiply that by the newright vector and add back the
8292                                         // center position
8293                                         // we also need to subtract the old position to undo the
8294                                         // displacement from the center, which we do with a
8295                                         // DotProduct, the subtraction/addition of center is also
8296                                         // optimized into DotProducts here
8297                                         l = DotProduct(right, center);
8298                                         for (i = 0;i < 4;i++)
8299                                         {
8300                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8301                                                 f = DotProduct(right, v1) - l;
8302                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8303                                         }
8304                                 }
8305                         }
8306                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8307                         {
8308 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8309 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8310 //                              rsurface.batchnormal3f_bufferoffset = 0;
8311                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8312                         }
8313                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8314                         {
8315 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8316 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8317 //                              rsurface.batchsvector3f_bufferoffset = 0;
8318 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8319 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8320 //                              rsurface.batchtvector3f_bufferoffset = 0;
8321                                 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);
8322                         }
8323                         break;
8324                 case Q3DEFORM_NORMAL:
8325                         // deform the normals to make reflections wavey
8326                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8327                         rsurface.batchnormal3f_vertexbuffer = NULL;
8328                         rsurface.batchnormal3f_bufferoffset = 0;
8329                         for (j = 0;j < batchnumvertices;j++)
8330                         {
8331                                 float vertex[3];
8332                                 float *normal = rsurface.batchnormal3f + 3*j;
8333                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8334                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8335                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8336                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8337                                 VectorNormalize(normal);
8338                         }
8339                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8340                         {
8341 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8342 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8343 //                              rsurface.batchsvector3f_bufferoffset = 0;
8344 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8345 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8346 //                              rsurface.batchtvector3f_bufferoffset = 0;
8347                                 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);
8348                         }
8349                         break;
8350                 case Q3DEFORM_WAVE:
8351                         // deform vertex array to make wavey water and flags and such
8352                         waveparms[0] = deform->waveparms[0];
8353                         waveparms[1] = deform->waveparms[1];
8354                         waveparms[2] = deform->waveparms[2];
8355                         waveparms[3] = deform->waveparms[3];
8356                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8357                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8358                         // this is how a divisor of vertex influence on deformation
8359                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8360                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8361 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8362 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8363 //                      rsurface.batchvertex3f_bufferoffset = 0;
8364 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8365 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8366 //                      rsurface.batchnormal3f_bufferoffset = 0;
8367                         for (j = 0;j < batchnumvertices;j++)
8368                         {
8369                                 // if the wavefunc depends on time, evaluate it per-vertex
8370                                 if (waveparms[3])
8371                                 {
8372                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8373                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8374                                 }
8375                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8376                         }
8377                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8378                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8379                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8380                         {
8381 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8382 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8383 //                              rsurface.batchsvector3f_bufferoffset = 0;
8384 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8385 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8386 //                              rsurface.batchtvector3f_bufferoffset = 0;
8387                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8388                         }
8389                         break;
8390                 case Q3DEFORM_BULGE:
8391                         // deform vertex array to make the surface have moving bulges
8392 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8393 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8394 //                      rsurface.batchvertex3f_bufferoffset = 0;
8395 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8396 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8397 //                      rsurface.batchnormal3f_bufferoffset = 0;
8398                         for (j = 0;j < batchnumvertices;j++)
8399                         {
8400                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8401                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8402                         }
8403                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8404                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8405                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8406                         {
8407 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8408 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8409 //                              rsurface.batchsvector3f_bufferoffset = 0;
8410 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8411 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8412 //                              rsurface.batchtvector3f_bufferoffset = 0;
8413                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8414                         }
8415                         break;
8416                 case Q3DEFORM_MOVE:
8417                         // deform vertex array
8418                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8419                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8420                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8421                         VectorScale(deform->parms, scale, waveparms);
8422 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8423 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8424 //                      rsurface.batchvertex3f_bufferoffset = 0;
8425                         for (j = 0;j < batchnumvertices;j++)
8426                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8427                         break;
8428                 }
8429         }
8430
8431         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
8432         {
8433         // generate texcoords based on the chosen texcoord source
8434                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
8435                 {
8436                 default:
8437                 case Q3TCGEN_TEXTURE:
8438                         break;
8439                 case Q3TCGEN_LIGHTMAP:
8440         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8441         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8442         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8443                         if (rsurface.batchtexcoordlightmap2f)
8444                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
8445                         break;
8446                 case Q3TCGEN_VECTOR:
8447         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8448         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8449         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8450                         for (j = 0;j < batchnumvertices;j++)
8451                         {
8452                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
8453                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
8454                         }
8455                         break;
8456                 case Q3TCGEN_ENVIRONMENT:
8457                         // make environment reflections using a spheremap
8458                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8459                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8460                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8461                         for (j = 0;j < batchnumvertices;j++)
8462                         {
8463                                 // identical to Q3A's method, but executed in worldspace so
8464                                 // carried models can be shiny too
8465
8466                                 float viewer[3], d, reflected[3], worldreflected[3];
8467
8468                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8469                                 // VectorNormalize(viewer);
8470
8471                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8472
8473                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8474                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8475                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8476                                 // note: this is proportinal to viewer, so we can normalize later
8477
8478                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8479                                 VectorNormalize(worldreflected);
8480
8481                                 // note: this sphere map only uses world x and z!
8482                                 // so positive and negative y will LOOK THE SAME.
8483                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8484                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8485                         }
8486                         break;
8487                 }
8488                 // the only tcmod that needs software vertex processing is turbulent, so
8489                 // check for it here and apply the changes if needed
8490                 // and we only support that as the first one
8491                 // (handling a mixture of turbulent and other tcmods would be problematic
8492                 //  without punting it entirely to a software path)
8493                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8494                 {
8495                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
8496                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
8497         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8498         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8499         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8500                         for (j = 0;j < batchnumvertices;j++)
8501                         {
8502                                 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);
8503                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8504                         }
8505                 }
8506         }
8507 }
8508
8509 void RSurf_DrawBatch(void)
8510 {
8511         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8512         // through the pipeline, killing it earlier in the pipeline would have
8513         // per-surface overhead rather than per-batch overhead, so it's best to
8514         // reject it here, before it hits glDraw.
8515         if (rsurface.batchnumtriangles == 0)
8516                 return;
8517 #if 0
8518         // batch debugging code
8519         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8520         {
8521                 int i;
8522                 int j;
8523                 int c;
8524                 const int *e;
8525                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8526                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8527                 {
8528                         c = e[i];
8529                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8530                         {
8531                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8532                                 {
8533                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8534                                                 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);
8535                                         break;
8536                                 }
8537                         }
8538                 }
8539         }
8540 #endif
8541         if (rsurface.batchmultidraw)
8542         {
8543                 // issue multiple draws rather than copying index data
8544                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
8545                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
8546                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
8547                 for (i = 0;i < numsurfaces;)
8548                 {
8549                         // combine consecutive surfaces as one draw
8550                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
8551                                 if (surfacelist[j] != surfacelist[k] + 1)
8552                                         break;
8553                         firstvertex = surfacelist[i]->num_firstvertex;
8554                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
8555                         firsttriangle = surfacelist[i]->num_firsttriangle;
8556                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
8557                         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);
8558                         i = j;
8559                 }
8560         }
8561         else
8562         {
8563                 // there is only one consecutive run of index data (may have been combined)
8564                 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);
8565         }
8566 }
8567
8568 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8569 {
8570         // pick the closest matching water plane
8571         int planeindex, vertexindex, bestplaneindex = -1;
8572         float d, bestd;
8573         vec3_t vert;
8574         const float *v;
8575         r_waterstate_waterplane_t *p;
8576         qboolean prepared = false;
8577         bestd = 0;
8578         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
8579         {
8580                 if(p->camera_entity != rsurface.texture->camera_entity)
8581                         continue;
8582                 d = 0;
8583                 if(!prepared)
8584                 {
8585                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
8586                         prepared = true;
8587                         if(rsurface.batchnumvertices == 0)
8588                                 break;
8589                 }
8590                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8591                 {
8592                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8593                         d += fabs(PlaneDiff(vert, &p->plane));
8594                 }
8595                 if (bestd > d || bestplaneindex < 0)
8596                 {
8597                         bestd = d;
8598                         bestplaneindex = planeindex;
8599                 }
8600         }
8601         return bestplaneindex;
8602         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8603         // this situation though, as it might be better to render single larger
8604         // batches with useless stuff (backface culled for example) than to
8605         // render multiple smaller batches
8606 }
8607
8608 void RSurf_SetupDepthAndCulling(void)
8609 {
8610         // submodels are biased to avoid z-fighting with world surfaces that they
8611         // may be exactly overlapping (avoids z-fighting artifacts on certain
8612         // doors and things in Quake maps)
8613         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8614         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8615         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8616         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8617 }
8618
8619 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8620 {
8621         int i, j;
8622         // transparent sky would be ridiculous
8623         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8624                 return;
8625         R_SetupShader_Generic_NoTexture(false, false);
8626         skyrenderlater = true;
8627         RSurf_SetupDepthAndCulling();
8628         GL_DepthMask(true);
8629
8630         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
8631         if (r_sky_scissor.integer)
8632         {
8633                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8634                 for (i = 0; i < texturenumsurfaces; i++)
8635                 {
8636                         const msurface_t *surf = texturesurfacelist[i];
8637                         const float *v;
8638                         float p[3];
8639                         float mins[3], maxs[3];
8640                         int scissor[4];
8641                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
8642                         {
8643                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
8644                                 if (j > 0)
8645                                 {
8646                                         if (mins[0] > p[0]) mins[0] = p[0];
8647                                         if (mins[1] > p[1]) mins[1] = p[1];
8648                                         if (mins[2] > p[2]) mins[2] = p[2];
8649                                         if (maxs[0] < p[0]) maxs[0] = p[0];
8650                                         if (maxs[1] < p[1]) maxs[1] = p[1];
8651                                         if (maxs[2] < p[2]) maxs[2] = p[2];
8652                                 }
8653                                 else
8654                                 {
8655                                         VectorCopy(p, mins);
8656                                         VectorCopy(p, maxs);
8657                                 }
8658                         }
8659                         if (!R_ScissorForBBox(mins, maxs, scissor))
8660                         {
8661                                 if (skyscissor[2])
8662                                 {
8663                                         if (skyscissor[0] > scissor[0])
8664                                         {
8665                                                 skyscissor[2] += skyscissor[0] - scissor[0];
8666                                                 skyscissor[0] = scissor[0];
8667                                         }
8668                                         if (skyscissor[1] > scissor[1])
8669                                         {
8670                                                 skyscissor[3] += skyscissor[1] - scissor[1];
8671                                                 skyscissor[1] = scissor[1];
8672                                         }
8673                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
8674                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
8675                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
8676                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
8677                                 }
8678                                 else
8679                                         Vector4Copy(scissor, skyscissor);
8680                         }
8681                 }
8682         }
8683
8684         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
8685         // skymasking on them, and Quake3 never did sky masking (unlike
8686         // software Quake and software Quake2), so disable the sky masking
8687         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8688         // and skymasking also looks very bad when noclipping outside the
8689         // level, so don't use it then either.
8690         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)
8691         {
8692                 R_Mesh_ResetTextureState();
8693                 if (skyrendermasked)
8694                 {
8695                         R_SetupShader_DepthOrShadow(false, false, false);
8696                         // depth-only (masking)
8697                         GL_ColorMask(0, 0, 0, 0);
8698                         // just to make sure that braindead drivers don't draw
8699                         // anything despite that colormask...
8700                         GL_BlendFunc(GL_ZERO, GL_ONE);
8701                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8702                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8703                 }
8704                 else
8705                 {
8706                         R_SetupShader_Generic_NoTexture(false, false);
8707                         // fog sky
8708                         GL_BlendFunc(GL_ONE, GL_ZERO);
8709                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
8710                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8711                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
8712                 }
8713                 RSurf_DrawBatch();
8714                 if (skyrendermasked)
8715                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8716         }
8717         R_Mesh_ResetTextureState();
8718         GL_Color(1, 1, 1, 1);
8719 }
8720
8721 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8722 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8723 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8724 {
8725         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
8726                 return;
8727         if (prepass)
8728         {
8729                 // render screenspace normalmap to texture
8730                 GL_DepthMask(true);
8731                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
8732                 RSurf_DrawBatch();
8733                 return;
8734         }
8735
8736         // bind lightmap texture
8737
8738         // water/refraction/reflection/camera surfaces have to be handled specially
8739         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
8740         {
8741                 int start, end, startplaneindex;
8742                 for (start = 0;start < texturenumsurfaces;start = end)
8743                 {
8744                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
8745                         if(startplaneindex < 0)
8746                         {
8747                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
8748                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
8749                                 end = start + 1;
8750                                 continue;
8751                         }
8752                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
8753                                 ;
8754                         // now that we have a batch using the same planeindex, render it
8755                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
8756                         {
8757                                 // render water or distortion background
8758                                 GL_DepthMask(true);
8759                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8760                                 RSurf_DrawBatch();
8761                                 // blend surface on top
8762                                 GL_DepthMask(false);
8763                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
8764                                 RSurf_DrawBatch();
8765                         }
8766                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
8767                         {
8768                                 // render surface with reflection texture as input
8769                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8770                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
8771                                 RSurf_DrawBatch();
8772                         }
8773                 }
8774                 return;
8775         }
8776
8777         // render surface batch normally
8778         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8779         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
8780         RSurf_DrawBatch();
8781 }
8782
8783 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8784 {
8785         int vi;
8786         int j;
8787         int texturesurfaceindex;
8788         int k;
8789         const msurface_t *surface;
8790         float surfacecolor4f[4];
8791
8792 //      R_Mesh_ResetTextureState();
8793         R_SetupShader_Generic_NoTexture(false, false);
8794
8795         GL_BlendFunc(GL_ONE, GL_ZERO);
8796         GL_DepthMask(writedepth);
8797
8798         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
8799         vi = 0;
8800         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8801         {
8802                 surface = texturesurfacelist[texturesurfaceindex];
8803                 k = (int)(((size_t)surface) / sizeof(msurface_t));
8804                 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
8805                 for (j = 0;j < surface->num_vertices;j++)
8806                 {
8807                         Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
8808                         vi++;
8809                 }
8810         }
8811         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f);
8812         RSurf_DrawBatch();
8813 }
8814
8815 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8816 {
8817         CHECKGLERROR
8818         RSurf_SetupDepthAndCulling();
8819         if (r_showsurfaces.integer && r_refdef.view.showdebug)
8820         {
8821                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
8822                 return;
8823         }
8824         switch (vid.renderpath)
8825         {
8826         case RENDERPATH_GL32:
8827         case RENDERPATH_GLES2:
8828                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8829                 break;
8830         }
8831         CHECKGLERROR
8832 }
8833
8834 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8835 {
8836         int i, j;
8837         int texturenumsurfaces, endsurface;
8838         texture_t *texture;
8839         const msurface_t *surface;
8840         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
8841
8842         RSurf_ActiveModelEntity(ent, true, true, false);
8843
8844         if (r_transparentdepthmasking.integer)
8845         {
8846                 qboolean setup = false;
8847                 for (i = 0;i < numsurfaces;i = j)
8848                 {
8849                         j = i + 1;
8850                         surface = rsurface.modelsurfaces + surfacelist[i];
8851                         texture = surface->texture;
8852                         rsurface.texture = R_GetCurrentTexture(texture);
8853                         rsurface.lightmaptexture = NULL;
8854                         rsurface.deluxemaptexture = NULL;
8855                         rsurface.uselightmaptexture = false;
8856                         // scan ahead until we find a different texture
8857                         endsurface = min(i + 1024, numsurfaces);
8858                         texturenumsurfaces = 0;
8859                         texturesurfacelist[texturenumsurfaces++] = surface;
8860                         for (;j < endsurface;j++)
8861                         {
8862                                 surface = rsurface.modelsurfaces + surfacelist[j];
8863                                 if (texture != surface->texture)
8864                                         break;
8865                                 texturesurfacelist[texturenumsurfaces++] = surface;
8866                         }
8867                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8868                                 continue;
8869                         // render the range of surfaces as depth
8870                         if (!setup)
8871                         {
8872                                 setup = true;
8873                                 GL_ColorMask(0,0,0,0);
8874                                 GL_Color(1,1,1,1);
8875                                 GL_DepthTest(true);
8876                                 GL_BlendFunc(GL_ONE, GL_ZERO);
8877                                 GL_DepthMask(true);
8878 //                              R_Mesh_ResetTextureState();
8879                         }
8880                         RSurf_SetupDepthAndCulling();
8881                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8882                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8883                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8884                         RSurf_DrawBatch();
8885                 }
8886                 if (setup)
8887                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8888         }
8889
8890         for (i = 0;i < numsurfaces;i = j)
8891         {
8892                 j = i + 1;
8893                 surface = rsurface.modelsurfaces + surfacelist[i];
8894                 texture = surface->texture;
8895                 rsurface.texture = R_GetCurrentTexture(texture);
8896                 // scan ahead until we find a different texture
8897                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
8898                 texturenumsurfaces = 0;
8899                 texturesurfacelist[texturenumsurfaces++] = surface;
8900                         rsurface.lightmaptexture = surface->lightmaptexture;
8901                         rsurface.deluxemaptexture = surface->deluxemaptexture;
8902                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8903                         for (;j < endsurface;j++)
8904                         {
8905                                 surface = rsurface.modelsurfaces + surfacelist[j];
8906                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
8907                                         break;
8908                                 texturesurfacelist[texturenumsurfaces++] = surface;
8909                         }
8910                 // render the range of surfaces
8911                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8912         }
8913         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
8914 }
8915
8916 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8917 {
8918         // transparent surfaces get pushed off into the transparent queue
8919         int surfacelistindex;
8920         const msurface_t *surface;
8921         vec3_t tempcenter, center;
8922         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8923         {
8924                 surface = texturesurfacelist[surfacelistindex];
8925                 if (r_transparent_sortsurfacesbynearest.integer)
8926                 {
8927                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
8928                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
8929                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
8930                 }
8931                 else
8932                 {
8933                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8934                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8935                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8936                 }
8937                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8938                 if (rsurface.entity->transparent_offset) // transparent offset
8939                 {
8940                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
8941                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
8942                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
8943                 }
8944                 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);
8945         }
8946 }
8947
8948 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8949 {
8950         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8951                 return;
8952         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8953                 return;
8954         RSurf_SetupDepthAndCulling();
8955         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
8956         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
8957         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
8958         RSurf_DrawBatch();
8959 }
8960
8961 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
8962 {
8963         CHECKGLERROR
8964         if (ui)
8965                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8966         else if (depthonly)
8967                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
8968         else if (prepass)
8969         {
8970                 if (!rsurface.texture->currentnumlayers)
8971                         return;
8972                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8973                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
8974                 else
8975                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8976         }
8977         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
8978                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8979         else if (!rsurface.texture->currentnumlayers)
8980                 return;
8981         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
8982         {
8983                 // in the deferred case, transparent surfaces were queued during prepass
8984                 if (!r_shadow_usingdeferredprepass)
8985                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
8986         }
8987         else
8988         {
8989                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8990                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8991         }
8992         CHECKGLERROR
8993 }
8994
8995 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass, qboolean ui)
8996 {
8997         int i, j;
8998         texture_t *texture;
8999         R_FrameData_SetMark();
9000         // break the surface list down into batches by texture and use of lightmapping
9001         for (i = 0;i < numsurfaces;i = j)
9002         {
9003                 j = i + 1;
9004                 // texture is the base texture pointer, rsurface.texture is the
9005                 // current frame/skin the texture is directing us to use (for example
9006                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9007                 // use skin 1 instead)
9008                 texture = surfacelist[i]->texture;
9009                 rsurface.texture = R_GetCurrentTexture(texture);
9010                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9011                 {
9012                         // if this texture is not the kind we want, skip ahead to the next one
9013                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9014                                 ;
9015                         continue;
9016                 }
9017                 if(depthonly || prepass)
9018                 {
9019                         rsurface.lightmaptexture = NULL;
9020                         rsurface.deluxemaptexture = NULL;
9021                         rsurface.uselightmaptexture = false;
9022                         // simply scan ahead until we find a different texture or lightmap state
9023                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9024                                 ;
9025                 }
9026                 else
9027                 {
9028                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9029                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9030                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9031                         // simply scan ahead until we find a different texture or lightmap state
9032                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9033                                 ;
9034                 }
9035                 // render the range of surfaces
9036                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass, ui);
9037         }
9038         R_FrameData_ReturnToMark();
9039 }
9040
9041 float locboxvertex3f[6*4*3] =
9042 {
9043         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9044         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9045         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9046         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9047         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9048         1,0,0, 0,0,0, 0,1,0, 1,1,0
9049 };
9050
9051 unsigned short locboxelements[6*2*3] =
9052 {
9053          0, 1, 2, 0, 2, 3,
9054          4, 5, 6, 4, 6, 7,
9055          8, 9,10, 8,10,11,
9056         12,13,14, 12,14,15,
9057         16,17,18, 16,18,19,
9058         20,21,22, 20,22,23
9059 };
9060
9061 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9062 {
9063         int i, j;
9064         cl_locnode_t *loc = (cl_locnode_t *)ent;
9065         vec3_t mins, size;
9066         float vertex3f[6*4*3];
9067         CHECKGLERROR
9068         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9069         GL_DepthMask(false);
9070         GL_DepthRange(0, 1);
9071         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9072         GL_DepthTest(true);
9073         GL_CullFace(GL_NONE);
9074         R_EntityMatrix(&identitymatrix);
9075
9076 //      R_Mesh_ResetTextureState();
9077
9078         i = surfacelist[0];
9079         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9080                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9081                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9082                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9083
9084         if (VectorCompare(loc->mins, loc->maxs))
9085         {
9086                 VectorSet(size, 2, 2, 2);
9087                 VectorMA(loc->mins, -0.5f, size, mins);
9088         }
9089         else
9090         {
9091                 VectorCopy(loc->mins, mins);
9092                 VectorSubtract(loc->maxs, loc->mins, size);
9093         }
9094
9095         for (i = 0;i < 6*4*3;)
9096                 for (j = 0;j < 3;j++, i++)
9097                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9098
9099         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
9100         R_SetupShader_Generic_NoTexture(false, false);
9101         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
9102 }
9103
9104 void R_DrawLocs(void)
9105 {
9106         int index;
9107         cl_locnode_t *loc, *nearestloc;
9108         vec3_t center;
9109         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9110         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9111         {
9112                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9113                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9114         }
9115 }
9116
9117 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9118 {
9119         if (decalsystem->decals)
9120                 Mem_Free(decalsystem->decals);
9121         memset(decalsystem, 0, sizeof(*decalsystem));
9122 }
9123
9124 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)
9125 {
9126         tridecal_t *decal;
9127         tridecal_t *decals;
9128         int i;
9129
9130         // expand or initialize the system
9131         if (decalsystem->maxdecals <= decalsystem->numdecals)
9132         {
9133                 decalsystem_t old = *decalsystem;
9134                 qboolean useshortelements;
9135                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9136                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9137                 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)));
9138                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9139                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9140                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9141                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9142                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9143                 if (decalsystem->numdecals)
9144                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9145                 if (old.decals)
9146                         Mem_Free(old.decals);
9147                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9148                         decalsystem->element3i[i] = i;
9149                 if (useshortelements)
9150                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9151                                 decalsystem->element3s[i] = i;
9152         }
9153
9154         // grab a decal and search for another free slot for the next one
9155         decals = decalsystem->decals;
9156         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9157         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
9158                 ;
9159         decalsystem->freedecal = i;
9160         if (decalsystem->numdecals <= i)
9161                 decalsystem->numdecals = i + 1;
9162
9163         // initialize the decal
9164         decal->lived = 0;
9165         decal->triangleindex = triangleindex;
9166         decal->surfaceindex = surfaceindex;
9167         decal->decalsequence = decalsequence;
9168         decal->color4f[0][0] = c0[0];
9169         decal->color4f[0][1] = c0[1];
9170         decal->color4f[0][2] = c0[2];
9171         decal->color4f[0][3] = 1;
9172         decal->color4f[1][0] = c1[0];
9173         decal->color4f[1][1] = c1[1];
9174         decal->color4f[1][2] = c1[2];
9175         decal->color4f[1][3] = 1;
9176         decal->color4f[2][0] = c2[0];
9177         decal->color4f[2][1] = c2[1];
9178         decal->color4f[2][2] = c2[2];
9179         decal->color4f[2][3] = 1;
9180         decal->vertex3f[0][0] = v0[0];
9181         decal->vertex3f[0][1] = v0[1];
9182         decal->vertex3f[0][2] = v0[2];
9183         decal->vertex3f[1][0] = v1[0];
9184         decal->vertex3f[1][1] = v1[1];
9185         decal->vertex3f[1][2] = v1[2];
9186         decal->vertex3f[2][0] = v2[0];
9187         decal->vertex3f[2][1] = v2[1];
9188         decal->vertex3f[2][2] = v2[2];
9189         decal->texcoord2f[0][0] = t0[0];
9190         decal->texcoord2f[0][1] = t0[1];
9191         decal->texcoord2f[1][0] = t1[0];
9192         decal->texcoord2f[1][1] = t1[1];
9193         decal->texcoord2f[2][0] = t2[0];
9194         decal->texcoord2f[2][1] = t2[1];
9195         TriangleNormal(v0, v1, v2, decal->plane);
9196         VectorNormalize(decal->plane);
9197         decal->plane[3] = DotProduct(v0, decal->plane);
9198 }
9199
9200 extern cvar_t cl_decals_bias;
9201 extern cvar_t cl_decals_models;
9202 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9203 // baseparms, parms, temps
9204 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)
9205 {
9206         int cornerindex;
9207         int index;
9208         float v[9][3];
9209         const float *vertex3f;
9210         const float *normal3f;
9211         int numpoints;
9212         float points[2][9][3];
9213         float temp[3];
9214         float tc[9][2];
9215         float f;
9216         float c[9][4];
9217         const int *e;
9218
9219         e = rsurface.modelelement3i + 3*triangleindex;
9220
9221         vertex3f = rsurface.modelvertex3f;
9222         normal3f = rsurface.modelnormal3f;
9223
9224         if (normal3f)
9225         {
9226                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9227                 {
9228                         index = 3*e[cornerindex];
9229                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
9230                 }
9231         }
9232         else
9233         {
9234                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9235                 {
9236                         index = 3*e[cornerindex];
9237                         VectorCopy(vertex3f + index, v[cornerindex]);
9238                 }
9239         }
9240
9241         // cull backfaces
9242         //TriangleNormal(v[0], v[1], v[2], normal);
9243         //if (DotProduct(normal, localnormal) < 0.0f)
9244         //      continue;
9245         // clip by each of the box planes formed from the projection matrix
9246         // if anything survives, we emit the decal
9247         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]);
9248         if (numpoints < 3)
9249                 return;
9250         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]);
9251         if (numpoints < 3)
9252                 return;
9253         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]);
9254         if (numpoints < 3)
9255                 return;
9256         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]);
9257         if (numpoints < 3)
9258                 return;
9259         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]);
9260         if (numpoints < 3)
9261                 return;
9262         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]);
9263         if (numpoints < 3)
9264                 return;
9265         // some part of the triangle survived, so we have to accept it...
9266         if (dynamic)
9267         {
9268                 // dynamic always uses the original triangle
9269                 numpoints = 3;
9270                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9271                 {
9272                         index = 3*e[cornerindex];
9273                         VectorCopy(vertex3f + index, v[cornerindex]);
9274                 }
9275         }
9276         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9277         {
9278                 // convert vertex positions to texcoords
9279                 Matrix4x4_Transform(projection, v[cornerindex], temp);
9280                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9281                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9282                 // calculate distance fade from the projection origin
9283                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9284                 f = bound(0.0f, f, 1.0f);
9285                 c[cornerindex][0] = r * f;
9286                 c[cornerindex][1] = g * f;
9287                 c[cornerindex][2] = b * f;
9288                 c[cornerindex][3] = 1.0f;
9289                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9290         }
9291         if (dynamic)
9292                 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);
9293         else
9294                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9295                         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);
9296 }
9297 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)
9298 {
9299         matrix4x4_t projection;
9300         decalsystem_t *decalsystem;
9301         qboolean dynamic;
9302         dp_model_t *model;
9303         const msurface_t *surface;
9304         const msurface_t *surfaces;
9305         const int *surfacelist;
9306         const texture_t *texture;
9307         int numtriangles;
9308         int numsurfacelist;
9309         int surfacelistindex;
9310         int surfaceindex;
9311         int triangleindex;
9312         float localorigin[3];
9313         float localnormal[3];
9314         float localmins[3];
9315         float localmaxs[3];
9316         float localsize;
9317         //float normal[3];
9318         float planes[6][4];
9319         float angles[3];
9320         bih_t *bih;
9321         int bih_triangles_count;
9322         int bih_triangles[256];
9323         int bih_surfaces[256];
9324
9325         decalsystem = &ent->decalsystem;
9326         model = ent->model;
9327         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9328         {
9329                 R_DecalSystem_Reset(&ent->decalsystem);
9330                 return;
9331         }
9332
9333         if (!model->brush.data_leafs && !cl_decals_models.integer)
9334         {
9335                 if (decalsystem->model)
9336                         R_DecalSystem_Reset(decalsystem);
9337                 return;
9338         }
9339
9340         if (decalsystem->model != model)
9341                 R_DecalSystem_Reset(decalsystem);
9342         decalsystem->model = model;
9343
9344         RSurf_ActiveModelEntity(ent, true, false, false);
9345
9346         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9347         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9348         VectorNormalize(localnormal);
9349         localsize = worldsize*rsurface.inversematrixscale;
9350         localmins[0] = localorigin[0] - localsize;
9351         localmins[1] = localorigin[1] - localsize;
9352         localmins[2] = localorigin[2] - localsize;
9353         localmaxs[0] = localorigin[0] + localsize;
9354         localmaxs[1] = localorigin[1] + localsize;
9355         localmaxs[2] = localorigin[2] + localsize;
9356
9357         //VectorCopy(localnormal, planes[4]);
9358         //VectorVectors(planes[4], planes[2], planes[0]);
9359         AnglesFromVectors(angles, localnormal, NULL, false);
9360         AngleVectors(angles, planes[0], planes[2], planes[4]);
9361         VectorNegate(planes[0], planes[1]);
9362         VectorNegate(planes[2], planes[3]);
9363         VectorNegate(planes[4], planes[5]);
9364         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9365         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9366         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9367         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9368         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9369         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9370
9371 #if 1
9372 // works
9373 {
9374         matrix4x4_t forwardprojection;
9375         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9376         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9377 }
9378 #else
9379 // broken
9380 {
9381         float projectionvector[4][3];
9382         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9383         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9384         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9385         projectionvector[0][0] = planes[0][0] * ilocalsize;
9386         projectionvector[0][1] = planes[1][0] * ilocalsize;
9387         projectionvector[0][2] = planes[2][0] * ilocalsize;
9388         projectionvector[1][0] = planes[0][1] * ilocalsize;
9389         projectionvector[1][1] = planes[1][1] * ilocalsize;
9390         projectionvector[1][2] = planes[2][1] * ilocalsize;
9391         projectionvector[2][0] = planes[0][2] * ilocalsize;
9392         projectionvector[2][1] = planes[1][2] * ilocalsize;
9393         projectionvector[2][2] = planes[2][2] * ilocalsize;
9394         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9395         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9396         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9397         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9398 }
9399 #endif
9400
9401         dynamic = model->surfmesh.isanimated;
9402         numsurfacelist = model->nummodelsurfaces;
9403         surfacelist = model->sortedmodelsurfaces;
9404         surfaces = model->data_surfaces;
9405
9406         bih = NULL;
9407         bih_triangles_count = -1;
9408         if(!dynamic)
9409         {
9410                 if(model->render_bih.numleafs)
9411                         bih = &model->render_bih;
9412                 else if(model->collision_bih.numleafs)
9413                         bih = &model->collision_bih;
9414         }
9415         if(bih)
9416                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
9417         if(bih_triangles_count == 0)
9418                 return;
9419         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
9420                 return;
9421         if(bih_triangles_count > 0)
9422         {
9423                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
9424                 {
9425                         surfaceindex = bih_surfaces[triangleindex];
9426                         surface = surfaces + surfaceindex;
9427                         texture = surface->texture;
9428                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9429                                 continue;
9430                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9431                                 continue;
9432                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
9433                 }
9434         }
9435         else
9436         {
9437                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9438                 {
9439                         surfaceindex = surfacelist[surfacelistindex];
9440                         surface = surfaces + surfaceindex;
9441                         // check cull box first because it rejects more than any other check
9442                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9443                                 continue;
9444                         // skip transparent surfaces
9445                         texture = surface->texture;
9446                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9447                                 continue;
9448                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9449                                 continue;
9450                         numtriangles = surface->num_triangles;
9451                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
9452                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
9453                 }
9454         }
9455 }
9456
9457 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9458 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)
9459 {
9460         int renderentityindex;
9461         float worldmins[3];
9462         float worldmaxs[3];
9463         entity_render_t *ent;
9464
9465         if (!cl_decals_newsystem.integer)
9466                 return;
9467
9468         worldmins[0] = worldorigin[0] - worldsize;
9469         worldmins[1] = worldorigin[1] - worldsize;
9470         worldmins[2] = worldorigin[2] - worldsize;
9471         worldmaxs[0] = worldorigin[0] + worldsize;
9472         worldmaxs[1] = worldorigin[1] + worldsize;
9473         worldmaxs[2] = worldorigin[2] + worldsize;
9474
9475         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9476
9477         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9478         {
9479                 ent = r_refdef.scene.entities[renderentityindex];
9480                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9481                         continue;
9482
9483                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9484         }
9485 }
9486
9487 typedef struct r_decalsystem_splatqueue_s
9488 {
9489         vec3_t worldorigin;
9490         vec3_t worldnormal;
9491         float color[4];
9492         float tcrange[4];
9493         float worldsize;
9494         unsigned int decalsequence;
9495 }
9496 r_decalsystem_splatqueue_t;
9497
9498 int r_decalsystem_numqueued = 0;
9499 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9500
9501 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)
9502 {
9503         r_decalsystem_splatqueue_t *queue;
9504
9505         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9506                 return;
9507
9508         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9509         VectorCopy(worldorigin, queue->worldorigin);
9510         VectorCopy(worldnormal, queue->worldnormal);
9511         Vector4Set(queue->color, r, g, b, a);
9512         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9513         queue->worldsize = worldsize;
9514         queue->decalsequence = cl.decalsequence++;
9515 }
9516
9517 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9518 {
9519         int i;
9520         r_decalsystem_splatqueue_t *queue;
9521
9522         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9523                 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);
9524         r_decalsystem_numqueued = 0;
9525 }
9526
9527 extern cvar_t cl_decals_max;
9528 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9529 {
9530         int i;
9531         decalsystem_t *decalsystem = &ent->decalsystem;
9532         int numdecals;
9533         unsigned int killsequence;
9534         tridecal_t *decal;
9535         float frametime;
9536         float lifetime;
9537
9538         if (!decalsystem->numdecals)
9539                 return;
9540
9541         if (r_showsurfaces.integer)
9542                 return;
9543
9544         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9545         {
9546                 R_DecalSystem_Reset(decalsystem);
9547                 return;
9548         }
9549
9550         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
9551         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9552
9553         if (decalsystem->lastupdatetime)
9554                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
9555         else
9556                 frametime = 0;
9557         decalsystem->lastupdatetime = r_refdef.scene.time;
9558         numdecals = decalsystem->numdecals;
9559
9560         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9561         {
9562                 if (decal->color4f[0][3])
9563                 {
9564                         decal->lived += frametime;
9565                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
9566                         {
9567                                 memset(decal, 0, sizeof(*decal));
9568                                 if (decalsystem->freedecal > i)
9569                                         decalsystem->freedecal = i;
9570                         }
9571                 }
9572         }
9573         decal = decalsystem->decals;
9574         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
9575                 numdecals--;
9576
9577         // collapse the array by shuffling the tail decals into the gaps
9578         for (;;)
9579         {
9580                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
9581                         decalsystem->freedecal++;
9582                 if (decalsystem->freedecal == numdecals)
9583                         break;
9584                 decal[decalsystem->freedecal] = decal[--numdecals];
9585         }
9586
9587         decalsystem->numdecals = numdecals;
9588
9589         if (numdecals <= 0)
9590         {
9591                 // if there are no decals left, reset decalsystem
9592                 R_DecalSystem_Reset(decalsystem);
9593         }
9594 }
9595
9596 extern skinframe_t *decalskinframe;
9597 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9598 {
9599         int i;
9600         decalsystem_t *decalsystem = &ent->decalsystem;
9601         int numdecals;
9602         tridecal_t *decal;
9603         float faderate;
9604         float alpha;
9605         float *v3f;
9606         float *c4f;
9607         float *t2f;
9608         const int *e;
9609         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9610         int numtris = 0;
9611
9612         numdecals = decalsystem->numdecals;
9613         if (!numdecals)
9614                 return;
9615
9616         if (r_showsurfaces.integer)
9617                 return;
9618
9619         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9620         {
9621                 R_DecalSystem_Reset(decalsystem);
9622                 return;
9623         }
9624
9625         // if the model is static it doesn't matter what value we give for
9626         // wantnormals and wanttangents, so this logic uses only rules applicable
9627         // to a model, knowing that they are meaningless otherwise
9628         RSurf_ActiveModelEntity(ent, false, false, false);
9629
9630         decalsystem->lastupdatetime = r_refdef.scene.time;
9631
9632         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9633
9634         // update vertex positions for animated models
9635         v3f = decalsystem->vertex3f;
9636         c4f = decalsystem->color4f;
9637         t2f = decalsystem->texcoord2f;
9638         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9639         {
9640                 if (!decal->color4f[0][3])
9641                         continue;
9642
9643                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9644                         continue;
9645
9646                 // skip backfaces
9647                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
9648                         continue;
9649
9650                 // update color values for fading decals
9651                 if (decal->lived >= cl_decals_time.value)
9652                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9653                 else
9654                         alpha = 1.0f;
9655
9656                 c4f[ 0] = decal->color4f[0][0] * alpha;
9657                 c4f[ 1] = decal->color4f[0][1] * alpha;
9658                 c4f[ 2] = decal->color4f[0][2] * alpha;
9659                 c4f[ 3] = 1;
9660                 c4f[ 4] = decal->color4f[1][0] * alpha;
9661                 c4f[ 5] = decal->color4f[1][1] * alpha;
9662                 c4f[ 6] = decal->color4f[1][2] * alpha;
9663                 c4f[ 7] = 1;
9664                 c4f[ 8] = decal->color4f[2][0] * alpha;
9665                 c4f[ 9] = decal->color4f[2][1] * alpha;
9666                 c4f[10] = decal->color4f[2][2] * alpha;
9667                 c4f[11] = 1;
9668
9669                 t2f[0] = decal->texcoord2f[0][0];
9670                 t2f[1] = decal->texcoord2f[0][1];
9671                 t2f[2] = decal->texcoord2f[1][0];
9672                 t2f[3] = decal->texcoord2f[1][1];
9673                 t2f[4] = decal->texcoord2f[2][0];
9674                 t2f[5] = decal->texcoord2f[2][1];
9675
9676                 // update vertex positions for animated models
9677                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
9678                 {
9679                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9680                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
9681                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
9682                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
9683                 }
9684                 else
9685                 {
9686                         VectorCopy(decal->vertex3f[0], v3f);
9687                         VectorCopy(decal->vertex3f[1], v3f + 3);
9688                         VectorCopy(decal->vertex3f[2], v3f + 6);
9689                 }
9690
9691                 if (r_refdef.fogenabled)
9692                 {
9693                         alpha = RSurf_FogVertex(v3f);
9694                         VectorScale(c4f, alpha, c4f);
9695                         alpha = RSurf_FogVertex(v3f + 3);
9696                         VectorScale(c4f + 4, alpha, c4f + 4);
9697                         alpha = RSurf_FogVertex(v3f + 6);
9698                         VectorScale(c4f + 8, alpha, c4f + 8);
9699                 }
9700
9701                 v3f += 9;
9702                 c4f += 12;
9703                 t2f += 6;
9704                 numtris++;
9705         }
9706
9707         if (numtris > 0)
9708         {
9709                 r_refdef.stats[r_stat_drawndecals] += numtris;
9710
9711                 // now render the decals all at once
9712                 // (this assumes they all use one particle font texture!)
9713                 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);
9714 //              R_Mesh_ResetTextureState();
9715                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
9716                 GL_DepthMask(false);
9717                 GL_DepthRange(0, 1);
9718                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9719                 GL_DepthTest(true);
9720                 GL_CullFace(GL_NONE);
9721                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9722                 R_SetupShader_Generic(decalskinframe->base, false, false, false);
9723                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
9724         }
9725 }
9726
9727 static void R_DrawModelDecals(void)
9728 {
9729         int i, numdecals;
9730
9731         // fade faster when there are too many decals
9732         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9733         for (i = 0;i < r_refdef.scene.numentities;i++)
9734                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9735
9736         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9737         for (i = 0;i < r_refdef.scene.numentities;i++)
9738                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9739                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9740
9741         R_DecalSystem_ApplySplatEntitiesQueue();
9742
9743         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9744         for (i = 0;i < r_refdef.scene.numentities;i++)
9745                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9746
9747         r_refdef.stats[r_stat_totaldecals] += numdecals;
9748
9749         if (r_showsurfaces.integer)
9750                 return;
9751
9752         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9753
9754         for (i = 0;i < r_refdef.scene.numentities;i++)
9755         {
9756                 if (!r_refdef.viewcache.entityvisible[i])
9757                         continue;
9758                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9759                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9760         }
9761 }
9762
9763 extern cvar_t mod_collision_bih;
9764 static void R_DrawDebugModel(void)
9765 {
9766         entity_render_t *ent = rsurface.entity;
9767         int i, j, flagsmask;
9768         const msurface_t *surface;
9769         dp_model_t *model = ent->model;
9770
9771         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
9772                 return;
9773
9774         if (r_showoverdraw.value > 0)
9775         {
9776                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
9777                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9778                 R_SetupShader_Generic_NoTexture(false, false);
9779                 GL_DepthTest(false);
9780                 GL_DepthMask(false);
9781                 GL_DepthRange(0, 1);
9782                 GL_BlendFunc(GL_ONE, GL_ONE);
9783                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9784                 {
9785                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9786                                 continue;
9787                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9788                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9789                         {
9790                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9791                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9792                                 if (!rsurface.texture->currentlayers->depthmask)
9793                                         GL_Color(c, 0, 0, 1.0f);
9794                                 else if (ent == r_refdef.scene.worldentity)
9795                                         GL_Color(c, c, c, 1.0f);
9796                                 else
9797                                         GL_Color(0, c, 0, 1.0f);
9798                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9799                                 RSurf_DrawBatch();
9800                         }
9801                 }
9802                 rsurface.texture = NULL;
9803         }
9804
9805         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9806
9807 //      R_Mesh_ResetTextureState();
9808         R_SetupShader_Generic_NoTexture(false, false);
9809         GL_DepthRange(0, 1);
9810         GL_DepthTest(!r_showdisabledepthtest.integer);
9811         GL_DepthMask(false);
9812         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9813
9814         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
9815         {
9816                 int triangleindex;
9817                 int bihleafindex;
9818                 qboolean cullbox = false;
9819                 const q3mbrush_t *brush;
9820                 const bih_t *bih = &model->collision_bih;
9821                 const bih_leaf_t *bihleaf;
9822                 float vertex3f[3][3];
9823                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9824                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
9825                 {
9826                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
9827                                 continue;
9828                         switch (bihleaf->type)
9829                         {
9830                         case BIH_BRUSH:
9831                                 brush = model->brush.data_brushes + bihleaf->itemindex;
9832                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
9833                                 {
9834                                         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);
9835                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
9836                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
9837                                 }
9838                                 break;
9839                         case BIH_COLLISIONTRIANGLE:
9840                                 triangleindex = bihleaf->itemindex;
9841                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
9842                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
9843                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
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(3, vertex3f[0], NULL, NULL);
9846                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9847                                 break;
9848                         case BIH_RENDERTRIANGLE:
9849                                 triangleindex = bihleaf->itemindex;
9850                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
9851                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
9852                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
9853                                 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);
9854                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
9855                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9856                                 break;
9857                         }
9858                 }
9859         }
9860
9861         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9862
9863 #ifndef USE_GLES2
9864         if (r_showtris.value > 0 && qglPolygonMode)
9865         {
9866                 if (r_showdisabledepthtest.integer)
9867                 {
9868                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9869                         GL_DepthMask(false);
9870                 }
9871                 else
9872                 {
9873                         GL_BlendFunc(GL_ONE, GL_ZERO);
9874                         GL_DepthMask(true);
9875                 }
9876                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
9877                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9878                 {
9879                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9880                                 continue;
9881                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9882                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9883                         {
9884                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9885                                 if (!rsurface.texture->currentlayers->depthmask)
9886                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9887                                 else if (ent == r_refdef.scene.worldentity)
9888                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9889                                 else
9890                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9891                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9892                                 RSurf_DrawBatch();
9893                         }
9894                 }
9895                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
9896                 rsurface.texture = NULL;
9897         }
9898
9899 # if 0
9900         // FIXME!  implement r_shownormals with just triangles
9901         if (r_shownormals.value != 0 && qglBegin)
9902         {
9903                 int l, k;
9904                 vec3_t v;
9905                 if (r_showdisabledepthtest.integer)
9906                 {
9907                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9908                         GL_DepthMask(false);
9909                 }
9910                 else
9911                 {
9912                         GL_BlendFunc(GL_ONE, GL_ZERO);
9913                         GL_DepthMask(true);
9914                 }
9915                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9916                 {
9917                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9918                                 continue;
9919                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9920                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9921                         {
9922                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
9923                                 qglBegin(GL_LINES);
9924                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
9925                                 {
9926                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9927                                         {
9928                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9929                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9930                                                 qglVertex3f(v[0], v[1], v[2]);
9931                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
9932                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9933                                                 qglVertex3f(v[0], v[1], v[2]);
9934                                         }
9935                                 }
9936                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
9937                                 {
9938                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9939                                         {
9940                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9941                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9942                                                 qglVertex3f(v[0], v[1], v[2]);
9943                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
9944                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9945                                                 qglVertex3f(v[0], v[1], v[2]);
9946                                         }
9947                                 }
9948                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
9949                                 {
9950                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9951                                         {
9952                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9953                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9954                                                 qglVertex3f(v[0], v[1], v[2]);
9955                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
9956                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9957                                                 qglVertex3f(v[0], v[1], v[2]);
9958                                         }
9959                                 }
9960                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
9961                                 {
9962                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
9963                                         {
9964                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
9965                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9966                                                 qglVertex3f(v[0], v[1], v[2]);
9967                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
9968                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
9969                                                 qglVertex3f(v[0], v[1], v[2]);
9970                                         }
9971                                 }
9972                                 qglEnd();
9973                                 CHECKGLERROR
9974                         }
9975                 }
9976                 rsurface.texture = NULL;
9977         }
9978 # endif
9979 #endif
9980 }
9981
9982 int r_maxsurfacelist = 0;
9983 const msurface_t **r_surfacelist = NULL;
9984 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass, qboolean ui)
9985 {
9986         int i, j, endj, flagsmask;
9987         dp_model_t *model = ent->model;
9988         msurface_t *surfaces;
9989         unsigned char *update;
9990         int numsurfacelist = 0;
9991         if (model == NULL)
9992                 return;
9993
9994         if (r_maxsurfacelist < model->num_surfaces)
9995         {
9996                 r_maxsurfacelist = model->num_surfaces;
9997                 if (r_surfacelist)
9998                         Mem_Free((msurface_t **)r_surfacelist);
9999                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10000         }
10001
10002         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10003                 RSurf_ActiveModelEntity(ent, false, false, false);
10004         else if (prepass)
10005                 RSurf_ActiveModelEntity(ent, true, true, true);
10006         else if (depthonly)
10007                 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
10008         else
10009                 RSurf_ActiveModelEntity(ent, true, true, false);
10010
10011         surfaces = model->data_surfaces;
10012         update = model->brushq1.lightmapupdateflags;
10013
10014         // update light styles
10015         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
10016         {
10017                 model_brush_lightstyleinfo_t *style;
10018                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10019                 {
10020                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10021                         {
10022                                 int *list = style->surfacelist;
10023                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10024                                 for (j = 0;j < style->numsurfaces;j++)
10025                                         update[list[j]] = true;
10026                         }
10027                 }
10028         }
10029
10030         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10031
10032         if (debug)
10033         {
10034                 R_DrawDebugModel();
10035                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10036                 return;
10037         }
10038
10039         rsurface.lightmaptexture = NULL;
10040         rsurface.deluxemaptexture = NULL;
10041         rsurface.uselightmaptexture = false;
10042         rsurface.texture = NULL;
10043         rsurface.rtlight = NULL;
10044         numsurfacelist = 0;
10045         // add visible surfaces to draw list
10046         if (ent == r_refdef.scene.worldentity)
10047         {
10048                 // for the world entity, check surfacevisible
10049                 for (i = 0;i < model->nummodelsurfaces;i++)
10050                 {
10051                         j = model->sortedmodelsurfaces[i];
10052                         if (r_refdef.viewcache.world_surfacevisible[j])
10053                                 r_surfacelist[numsurfacelist++] = surfaces + j;
10054                 }
10055         }
10056         else if (ui)
10057         {
10058                 // for ui we have to preserve the order of surfaces
10059                 for (i = 0; i < model->nummodelsurfaces; i++)
10060                         r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i;
10061         }
10062         else
10063         {
10064                 // add all surfaces
10065                 for (i = 0; i < model->nummodelsurfaces; i++)
10066                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10067         }
10068         // don't do anything if there were no surfaces
10069         if (!numsurfacelist)
10070         {
10071                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10072                 return;
10073         }
10074         // update lightmaps if needed
10075         if (update)
10076         {
10077                 int updated = 0;
10078                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10079                 {
10080                         if (update[j])
10081                         {
10082                                 updated++;
10083                                 R_BuildLightMap(ent, surfaces + j);
10084                         }
10085                 }
10086         }
10087
10088         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass, ui);
10089
10090         // add to stats if desired
10091         if (r_speeds.integer && !skysurfaces && !depthonly)
10092         {
10093                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
10094                 for (j = 0;j < numsurfacelist;j++)
10095                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
10096         }
10097
10098         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
10099 }
10100
10101 void R_DebugLine(vec3_t start, vec3_t end)
10102 {
10103         dp_model_t *mod = CL_Mesh_UI();
10104         msurface_t *surf;
10105         int e0, e1, e2, e3;
10106         float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
10107         float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
10108         float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
10109         vec4_t w[2], s[2];
10110
10111         // transform to screen coords first
10112         Vector4Set(w[0], start[0], start[1], start[2], 1);
10113         Vector4Set(w[1], end[0], end[1], end[2], 1);
10114         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
10115         R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
10116         x1 = s[0][0] * vid_conwidth.value / vid.width;
10117         y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
10118         x2 = s[1][0] * vid_conwidth.value / vid.width;
10119         y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
10120         //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
10121
10122         // add the line to the UI mesh for drawing later
10123
10124         // width is measured in real pixels
10125         if (fabs(x2 - x1) > fabs(y2 - y1))
10126         {
10127                 offsetx = 0;
10128                 offsety = 0.5f * width * vid_conheight.value / vid.height;
10129         }
10130         else
10131         {
10132                 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
10133                 offsety = 0;
10134         }
10135         surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX), true);
10136         e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10137         e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10138         e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
10139         e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
10140         Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
10141         Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
10142
10143 }
10144
10145
10146 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10147 {
10148         int q;
10149         static texture_t texture;
10150         static msurface_t surface;
10151         const msurface_t *surfacelist = &surface;
10152
10153         // fake enough texture and surface state to render this geometry
10154
10155         texture.update_lastrenderframe = -1; // regenerate this texture
10156         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10157         texture.basealpha = 1.0f;
10158         texture.currentskinframe = skinframe;
10159         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10160         texture.offsetmapping = OFFSETMAPPING_OFF;
10161         texture.offsetscale = 1;
10162         texture.specularscalemod = 1;
10163         texture.specularpowermod = 1;
10164         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
10165         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
10166         // JUST GREP FOR "specularscalemod = 1".
10167
10168         for (q = 0; q < 3; q++)
10169         {
10170                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
10171                 texture.render_modellight_lightdir[q] = q == 2;
10172                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10173                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
10174                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
10175                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
10176                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
10177                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
10178                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
10179                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
10180         }
10181         texture.currentalpha = 1.0f;
10182
10183         surface.texture = &texture;
10184         surface.num_triangles = numtriangles;
10185         surface.num_firsttriangle = firsttriangle;
10186         surface.num_vertices = numvertices;
10187         surface.num_firstvertex = firstvertex;
10188
10189         // now render it
10190         rsurface.texture = R_GetCurrentTexture(surface.texture);
10191         rsurface.lightmaptexture = NULL;
10192         rsurface.deluxemaptexture = NULL;
10193         rsurface.uselightmaptexture = false;
10194         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10195 }
10196
10197 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)
10198 {
10199         static msurface_t surface;
10200         const msurface_t *surfacelist = &surface;
10201
10202         // fake enough texture and surface state to render this geometry
10203         surface.texture = texture;
10204         surface.num_triangles = numtriangles;
10205         surface.num_firsttriangle = firsttriangle;
10206         surface.num_vertices = numvertices;
10207         surface.num_firstvertex = firstvertex;
10208
10209         // now render it
10210         rsurface.texture = R_GetCurrentTexture(surface.texture);
10211         rsurface.lightmaptexture = NULL;
10212         rsurface.deluxemaptexture = NULL;
10213         rsurface.uselightmaptexture = false;
10214         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10215 }