Remove old decal system, cl_decals_newsystem has been on by default for 10 years...
[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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
63 cvar_t r_motionblur_minblur = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
65 cvar_t r_motionblur_velocityfactor = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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 = {CVAR_CLIENT, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {CVAR_CLIENT, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {CVAR_CLIENT, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {CVAR_CLIENT, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {CVAR_CLIENT, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {CVAR_CLIENT, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showbboxes_client = {CVAR_CLIENT, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 cvar_t r_showsurfaces = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {CVAR_CLIENT, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
96 cvar_t r_drawentities = {CVAR_CLIENT, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
97 cvar_t r_draw2d = {CVAR_CLIENT, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
98 cvar_t r_drawworld = {CVAR_CLIENT, "r_drawworld","1", "draw world (most static stuff)"};
99 cvar_t r_drawviewmodel = {CVAR_CLIENT, "r_drawviewmodel","1", "draw your weapon model"};
100 cvar_t r_drawexteriormodel = {CVAR_CLIENT, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
101 cvar_t r_cullentities_trace = {CVAR_CLIENT, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
102 cvar_t r_cullentities_trace_entityocclusion = {CVAR_CLIENT, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull"};
103 cvar_t r_cullentities_trace_samples = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
106 cvar_t r_cullentities_trace_expand = {CVAR_CLIENT, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
107 cvar_t r_cullentities_trace_pad = {CVAR_CLIENT, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
108 cvar_t r_cullentities_trace_delay = {CVAR_CLIENT, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
109 cvar_t r_cullentities_trace_eyejitter = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
111 cvar_t r_speeds = {CVAR_CLIENT, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
112 cvar_t r_fullbright = {CVAR_CLIENT, "r_fullbright","0", "makes map very bright and renders faster"};
113
114 cvar_t r_fullbright_directed = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
116 cvar_t r_fullbright_directed_diffuse = {CVAR_CLIENT, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
117 cvar_t r_fullbright_directed_pitch = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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_CLIENT | CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
121 cvar_t r_dynamic = {CVAR_CLIENT | CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
122 cvar_t r_fullbrights = {CVAR_CLIENT | CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
123 cvar_t r_shadows = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
125 cvar_t r_shadows_throwdistance = {CVAR_CLIENT | CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
126 cvar_t r_shadows_throwdirection = {CVAR_CLIENT | CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
127 cvar_t r_shadows_drawafterrtlighting = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
129 cvar_t r_shadows_focus = {CVAR_CLIENT | CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
130 cvar_t r_shadows_shadowmapscale = {CVAR_CLIENT | 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_CLIENT | 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 = {CVAR_CLIENT, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
133 cvar_t r_polygonoffset_submodel_factor = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
136 cvar_t r_polygonoffset_decals_offset = {CVAR_CLIENT, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
137 cvar_t r_fog_exp2 = {CVAR_CLIENT, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
138 cvar_t r_fog_clear = {CVAR_CLIENT, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
139 cvar_t r_drawfog = {CVAR_CLIENT | CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
140 cvar_t r_transparentdepthmasking = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
142 cvar_t r_transparent_sortmaxdist = {CVAR_CLIENT | CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
143 cvar_t r_transparent_sortarraysize = {CVAR_CLIENT | CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
144 cvar_t r_celshading = {CVAR_CLIENT | 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_CLIENT | 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 = {CVAR_CLIENT, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
148 cvar_t gl_fogdensity = {CVAR_CLIENT, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
149 cvar_t gl_fogred = {CVAR_CLIENT, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
150 cvar_t gl_foggreen = {CVAR_CLIENT, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
151 cvar_t gl_fogblue = {CVAR_CLIENT, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
152 cvar_t gl_fogstart = {CVAR_CLIENT, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
153 cvar_t gl_fogend = {CVAR_CLIENT, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
154 cvar_t gl_skyclip = {CVAR_CLIENT, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
155
156 cvar_t r_texture_dds_load = {CVAR_CLIENT | 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_CLIENT | 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 = {CVAR_CLIENT, "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_CLIENT | CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
161 static cvar_t r_glsl = {CVAR_CLIENT | CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
162
163 cvar_t r_usedepthtextures = {CVAR_CLIENT | 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_CLIENT | 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 = {CVAR_CLIENT, "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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
168 cvar_t r_viewscale_fpsscaling_min = {CVAR_CLIENT | CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
169 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
173
174 cvar_t r_glsl_skeletal = {CVAR_CLIENT | CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
175 cvar_t r_glsl_deluxemapping = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
179 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
182 cvar_t r_glsl_offsetmapping_lod = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
185 cvar_t r_glsl_postprocess_uservec1 = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
197 cvar_t r_water_resolutionmultiplier = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
199 cvar_t r_water_reflectdistort = {CVAR_CLIENT | CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
200 cvar_t r_water_scissormode = {CVAR_CLIENT, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
201 cvar_t r_water_lowquality = {CVAR_CLIENT, "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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
205 cvar_t r_lerpmodels = {CVAR_CLIENT | CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
206 cvar_t r_lerplightstyles = {CVAR_CLIENT | CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
207 cvar_t r_waterscroll = {CVAR_CLIENT | CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
208
209 cvar_t r_bloom = {CVAR_CLIENT | CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
210 cvar_t r_bloom_colorscale = {CVAR_CLIENT | CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
211
212 cvar_t r_bloom_brighten = {CVAR_CLIENT | CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
213 cvar_t r_bloom_blur = {CVAR_CLIENT | CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
214 cvar_t r_bloom_resolution = {CVAR_CLIENT | 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_CLIENT | CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
216 cvar_t r_bloom_colorsubtract = {CVAR_CLIENT | CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
217 cvar_t r_bloom_scenebrightness = {CVAR_CLIENT | CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
218
219 cvar_t r_hdr_scenebrightness = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
220 cvar_t r_hdr_glowintensity = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
221 cvar_t r_hdr_irisadaptation = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
222 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
223 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
224 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_CLIENT | CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
225 cvar_t r_hdr_irisadaptation_value = {CVAR_CLIENT, "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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
229
230 cvar_t r_smoothnormals_areaweighting = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "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 = {CVAR_CLIENT, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
235
236 cvar_t r_test = {CVAR_CLIENT, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
237
238 cvar_t r_batch_multidraw = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
241 cvar_t r_batch_dynamicbuffer = {CVAR_CLIENT | CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
242
243 cvar_t r_glsl_saturation = {CVAR_CLIENT | CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
244 cvar_t r_glsl_saturation_redcompensate = {CVAR_CLIENT | 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_CLIENT | 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_CLIENT | 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_CLIENT | CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
252         {CVAR_CLIENT | CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
253         {CVAR_CLIENT | CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
254         {CVAR_CLIENT | 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(&cvars_all, "gl_fogenable", "0");
350                 Cvar_Set(&cvars_all, "gl_fogdensity", "0.2");
351                 Cvar_Set(&cvars_all, "gl_fogred", "0.3");
352                 Cvar_Set(&cvars_all, "gl_foggreen", "0.3");
353                 Cvar_Set(&cvars_all, "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         // LadyHavoc: 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(cmd_state_t *cmd)
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(cmd_state_t *cmd)
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 && !notrippy)
1733                 {
1734                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1735                         if (r_shadow_bouncegrid_state.directional)
1736                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1737                 }
1738                 GL_BlendFunc(t->currentblendfunc[0], t->currentblendfunc[1]);
1739                 blendfuncflags = R_BlendFuncFlags(t->currentblendfunc[0], t->currentblendfunc[1]);
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 && !notrippy)
1822                 {
1823                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
1824                         if (r_shadow_bouncegrid_state.directional)
1825                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
1826                 }
1827                 GL_BlendFunc(t->currentblendfunc[0], t->currentblendfunc[1]);
1828                 blendfuncflags = R_BlendFuncFlags(t->currentblendfunc[0], t->currentblendfunc[1]);
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);