Rework r_shadow_shadowmode to be more maintainable and understandable - it now caches...
[xonotic/darkplaces.git] / r_shadow.c
1 #include "quakedef.h"
2 #include "r_shadow.h"
3 #include "cl_collision.h"
4 #include "portals.h"
5 #include "image.h"
6
7 static void R_Shadow_EditLights_Init(void);
8
9 typedef enum r_shadow_rendermode_e
10 {
11         R_SHADOW_RENDERMODE_NONE,
12         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
13         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
14         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
15         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
16         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
17         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
18         R_SHADOW_RENDERMODE_LIGHT_GLSL,
19         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
20         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
21         R_SHADOW_RENDERMODE_SHADOWMAP2D
22 }
23 r_shadow_rendermode_t;
24
25 typedef enum r_shadow_shadowmode_e
26 {
27         R_SHADOW_SHADOWMODE_DISABLED,
28         R_SHADOW_SHADOWMODE_SHADOWMAP2D
29 }
30 r_shadow_shadowmode_t;
31
32 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
33 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
34 int r_shadow_scenemaxlights;
35 int r_shadow_scenenumlights;
36 rtlight_t **r_shadow_scenelightlist; // includes both static lights and dlights, as filtered by appropriate flags
37 qboolean r_shadow_usingshadowmap2d;
38 qboolean r_shadow_usingshadowmaportho;
39 int r_shadow_shadowmapside;
40 float r_shadow_lightshadowmap_texturescale[4]; // xy = scale, zw = offset
41 float r_shadow_lightshadowmap_parameters[4]; // x = frustum width in pixels (excludes border), y = z scale, z = size of viewport, w = z center
42 float r_shadow_modelshadowmap_texturescale[4]; // xy = scale, zw = offset
43 float r_shadow_modelshadowmap_parameters[4]; // xyz = scale, w = shadow brightness
44 #if 0
45 int r_shadow_drawbuffer;
46 int r_shadow_readbuffer;
47 #endif
48 int r_shadow_cullface_front, r_shadow_cullface_back;
49 GLuint r_shadow_fbo2d;
50 int r_shadow_shadowmode_shadowmapping; // cached value of r_shadow_shadowmapping cvar
51 int r_shadow_shadowmode_deferred; // cached value of r_shadow_deferred cvar
52 r_shadow_shadowmode_t r_shadow_shadowmode;
53 int r_shadow_shadowmapfilterquality;
54 int r_shadow_shadowmapdepthbits;
55 int r_shadow_shadowmapmaxsize;
56 int r_shadow_shadowmaptexturesize;
57 qboolean r_shadow_shadowmapvsdct;
58 qboolean r_shadow_shadowmapsampler;
59 qboolean r_shadow_shadowmapshadowsampler;
60 int r_shadow_shadowmappcf;
61 int r_shadow_shadowmapborder;
62 matrix4x4_t r_shadow_shadowmapmatrix;
63 int r_shadow_lightscissor[4];
64 qboolean r_shadow_usingdeferredprepass;
65 qboolean r_shadow_shadowmapdepthtexture;
66 mod_alloclightmap_state_t r_shadow_shadowmapatlas_state;
67 int r_shadow_shadowmapatlas_modelshadows_x;
68 int r_shadow_shadowmapatlas_modelshadows_y;
69 int r_shadow_shadowmapatlas_modelshadows_size;
70 int maxshadowtriangles;
71 int *shadowelements;
72
73 int maxshadowvertices;
74 float *shadowvertex3f;
75
76 int maxshadowmark;
77 int numshadowmark;
78 int *shadowmark;
79 int *shadowmarklist;
80 int shadowmarkcount;
81
82 int maxshadowsides;
83 int numshadowsides;
84 unsigned char *shadowsides;
85 int *shadowsideslist;
86
87 int maxvertexupdate;
88 int *vertexupdate;
89 int *vertexremap;
90 int vertexupdatenum;
91
92 int r_shadow_buffer_numleafpvsbytes;
93 unsigned char *r_shadow_buffer_visitingleafpvs;
94 unsigned char *r_shadow_buffer_leafpvs;
95 int *r_shadow_buffer_leaflist;
96
97 int r_shadow_buffer_numsurfacepvsbytes;
98 unsigned char *r_shadow_buffer_surfacepvs;
99 int *r_shadow_buffer_surfacelist;
100 unsigned char *r_shadow_buffer_surfacesides;
101
102 int r_shadow_buffer_numshadowtrispvsbytes;
103 unsigned char *r_shadow_buffer_shadowtrispvs;
104 int r_shadow_buffer_numlighttrispvsbytes;
105 unsigned char *r_shadow_buffer_lighttrispvs;
106
107 rtexturepool_t *r_shadow_texturepool;
108 rtexture_t *r_shadow_attenuationgradienttexture;
109 skinframe_t *r_shadow_lightcorona;
110 rtexture_t *r_shadow_shadowmap2ddepthbuffer;
111 rtexture_t *r_shadow_shadowmap2ddepthtexture;
112 rtexture_t *r_shadow_shadowmapvsdcttexture;
113
114 GLuint r_shadow_prepassgeometryfbo;
115 GLuint r_shadow_prepasslightingdiffusespecularfbo;
116 GLuint r_shadow_prepasslightingdiffusefbo;
117 int r_shadow_prepass_width;
118 int r_shadow_prepass_height;
119 rtexture_t *r_shadow_prepassgeometrydepthbuffer;
120 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
121 rtexture_t *r_shadow_prepasslightingdiffusetexture;
122 rtexture_t *r_shadow_prepasslightingspeculartexture;
123
124 int r_shadow_viewfbo;
125 rtexture_t *r_shadow_viewdepthtexture;
126 rtexture_t *r_shadow_viewcolortexture;
127 int r_shadow_viewx;
128 int r_shadow_viewy;
129 int r_shadow_viewwidth;
130 int r_shadow_viewheight;
131
132 // lights are reloaded when this changes
133 char r_shadow_mapname[MAX_QPATH];
134
135 // buffer for doing corona fading
136 unsigned int r_shadow_occlusion_buf = 0;
137
138 // used only for light filters (cubemaps)
139 rtexturepool_t *r_shadow_filters_texturepool;
140
141 cvar_t r_shadow_bumpscale_basetexture = {CVAR_CLIENT, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
142 cvar_t r_shadow_bumpscale_bumpmap = {CVAR_CLIENT, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
143 cvar_t r_shadow_debuglight = {CVAR_CLIENT, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
144 cvar_t r_shadow_deferred = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
145 cvar_t r_shadow_usebihculling = {CVAR_CLIENT, "r_shadow_usebihculling", "1", "use BIH (Bounding Interval Hierarchy) for culling lit surfaces instead of BSP (Binary Space Partitioning)"};
146 cvar_t r_shadow_usenormalmap = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
147 cvar_t r_shadow_gloss = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
148 cvar_t r_shadow_gloss2intensity = {CVAR_CLIENT, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
149 cvar_t r_shadow_glossintensity = {CVAR_CLIENT, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
150 cvar_t r_shadow_glossexponent = {CVAR_CLIENT, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
151 cvar_t r_shadow_gloss2exponent = {CVAR_CLIENT, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
152 cvar_t r_shadow_glossexact = {CVAR_CLIENT, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
153 cvar_t r_shadow_lightattenuationdividebias = {CVAR_CLIENT, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
154 cvar_t r_shadow_lightattenuationlinearscale = {CVAR_CLIENT, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
155 cvar_t r_shadow_lightintensityscale = {CVAR_CLIENT, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
156 cvar_t r_shadow_lightradiusscale = {CVAR_CLIENT, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
157 cvar_t r_shadow_projectdistance = {CVAR_CLIENT, "r_shadow_projectdistance", "0", "how far to cast shadows"};
158 cvar_t r_shadow_frontsidecasting = {CVAR_CLIENT, "r_shadow_frontsidecasting", "1", "whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)"};
159 cvar_t r_shadow_realtime_dlight = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
160 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
161 cvar_t r_shadow_realtime_dlight_svbspculling = {CVAR_CLIENT, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
162 cvar_t r_shadow_realtime_dlight_portalculling = {CVAR_CLIENT, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
163 cvar_t r_shadow_realtime_world = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_realtime_world", "0", "enables rendering of full world lighting (whether loaded from the map, or a .rtlights file, or a .ent file, or a .lights file produced by hlight)"};
164 cvar_t r_shadow_realtime_world_importlightentitiesfrommap = {CVAR_CLIENT, "r_shadow_realtime_world_importlightentitiesfrommap", "1", "load lights from .ent file or map entities at startup if no .rtlights or .lights file is present (if set to 2, always use the .ent or map entities)"};
165 cvar_t r_shadow_realtime_world_lightmaps = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_realtime_world_lightmaps", "0", "brightness to render lightmaps when using full world lighting, try 0.5 for a tenebrae-like appearance"};
166 cvar_t r_shadow_realtime_world_shadows = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
167 cvar_t r_shadow_realtime_world_compile = {CVAR_CLIENT, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
168 cvar_t r_shadow_realtime_world_compileshadow = {CVAR_CLIENT, "r_shadow_realtime_world_compileshadow", "1", "enables compilation of shadows from world lights for higher performance rendering"};
169 cvar_t r_shadow_realtime_world_compilesvbsp = {CVAR_CLIENT, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
170 cvar_t r_shadow_realtime_world_compileportalculling = {CVAR_CLIENT, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
171 cvar_t r_shadow_scissor = {CVAR_CLIENT, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
172 cvar_t r_shadow_shadowmapping = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (shadow rendering by depth texture sampling)"};
173 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
174 cvar_t r_shadow_shadowmapping_useshadowsampler = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"};
175 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
176 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
177 cvar_t r_shadow_shadowmapping_minsize = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "limit of shadowmap side size - must be at least r_shadow_shadowmapping_bordersize+2"};
178 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "limit of shadowmap side size - can not be more than 1/8th of atlassize because lights store 6 sides (2x3 grid) and sometimes 12 sides (4x3 grid for shadows from EF_NOSELFSHADOW entities) and there are multiple lights..."};
179 cvar_t r_shadow_shadowmapping_texturesize = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_texturesize", "8192", "size of shadowmap atlas texture - all shadowmaps are packed into this texture at frame start"};
180 cvar_t r_shadow_shadowmapping_precision = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
181 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
182 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
183 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "5", "shadowmap size bias for filtering"};
184 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
185 cvar_t r_shadow_shadowmapping_bias = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
186 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
187 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
188 cvar_t r_shadow_sortsurfaces = {CVAR_CLIENT, "r_shadow_sortsurfaces", "1", "improve performance by sorting illuminated surfaces by texture"};
189 cvar_t r_shadow_culllights_pvs = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_pvs", "1", "check if light overlaps any visible bsp leafs when determining if the light is visible"};
190 cvar_t r_shadow_culllights_trace = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace", "1", "use raytraces from the eye to random places within light bounds to determine if the light is visible"};
191 cvar_t r_shadow_culllights_trace_eyejitter = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_eyejitter", "16", "offset eye location randomly by this much"};
192 cvar_t r_shadow_culllights_trace_enlarge = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_enlarge", "0", "make light bounds bigger by *(1.0+enlarge)"};
193 cvar_t r_shadow_culllights_trace_expand = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_expand", "8", "make light bounds bigger by this many units"};
194 cvar_t r_shadow_culllights_trace_pad = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_pad", "8", "accept traces that hit within this many units of the light bounds"};
195 cvar_t r_shadow_culllights_trace_samples = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_samples", "16", "use this many traces to random positions (in addition to center trace)"};
196 cvar_t r_shadow_culllights_trace_tempsamples = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_tempsamples", "16", "use this many traces if the light was created by csqc (no inter-frame caching), -1 disables the check (to avoid flicker entirely)"};
197 cvar_t r_shadow_culllights_trace_delay = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_culllights_trace_delay", "1", "light will be considered visible for this many seconds after any trace connects"};
198 cvar_t r_shadow_bouncegrid = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid", "0", "perform particle tracing for indirect lighting (Global Illumination / radiosity) using a 3D texture covering the scene, only active on levels with realtime lights active (r_shadow_realtime_world is usually required for these)"};
199 cvar_t r_shadow_bouncegrid_blur = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_blur", "0", "apply a 1-radius blur on bouncegrid to denoise it and deal with boundary issues with surfaces"};
200 cvar_t r_shadow_bouncegrid_dynamic_bounceminimumintensity = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_bounceminimumintensity", "0.05", "stop bouncing once intensity drops below this fraction of the original particle color"};
201 cvar_t r_shadow_bouncegrid_dynamic_culllightpaths = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_culllightpaths", "0", "skip accumulating light in the bouncegrid texture where the light paths are out of view (dynamic mode only)"};
202 cvar_t r_shadow_bouncegrid_dynamic_directionalshading = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_directionalshading", "1", "use diffuse shading rather than ambient, 3D texture becomes 8x as many pixels to hold the additional data"};
203 cvar_t r_shadow_bouncegrid_dynamic_dlightparticlemultiplier = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_dlightparticlemultiplier", "1", "if set to a high value like 16 this can make dlights look great, but 0 is recommended for performance reasons"};
204 cvar_t r_shadow_bouncegrid_dynamic_hitmodels = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_hitmodels", "0", "enables hitting character model geometry (SLOW)"};
205 cvar_t r_shadow_bouncegrid_dynamic_lightradiusscale = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_lightradiusscale", "5", "particles stop at this fraction of light radius (can be more than 1)"};
206 cvar_t r_shadow_bouncegrid_dynamic_maxbounce = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_maxbounce", "5", "maximum number of bounces for a particle (minimum is 0)"};
207 cvar_t r_shadow_bouncegrid_dynamic_maxphotons = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_maxphotons", "25000", "upper bound on photons to shoot per update, divided proportionately between lights - normally the number of photons is calculated by energyperphoton"};
208 cvar_t r_shadow_bouncegrid_dynamic_quality = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_quality", "1", "amount of photons that should be fired (this is multiplied by spacing ^ 2 to make it adaptive with spacing changes)"};
209 cvar_t r_shadow_bouncegrid_dynamic_spacing = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_spacing", "64", "unit size of bouncegrid pixel"};
210 cvar_t r_shadow_bouncegrid_dynamic_updateinterval = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_updateinterval", "0", "update bouncegrid texture once per this many seconds, useful values are 0, 0.05, or 1000000"};
211 cvar_t r_shadow_bouncegrid_dynamic_x = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_x", "64", "maximum texture size of bouncegrid on X axis"};
212 cvar_t r_shadow_bouncegrid_dynamic_y = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_y", "64", "maximum texture size of bouncegrid on Y axis"};
213 cvar_t r_shadow_bouncegrid_dynamic_z = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_dynamic_z", "32", "maximum texture size of bouncegrid on Z axis"};
214 cvar_t r_shadow_bouncegrid_floatcolors = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_floatcolors", "1", "upload texture as RGBA16F (or RGBA32F when set to 2) rather than RGBA8 format - this gives more dynamic range and accuracy"};
215 cvar_t r_shadow_bouncegrid_includedirectlighting = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_includedirectlighting", "0", "allows direct lighting to be recorded, not just indirect (gives an effect somewhat like r_shadow_realtime_world_lightmaps)"};
216 cvar_t r_shadow_bouncegrid_intensity = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_intensity", "4", "overall brightness of bouncegrid texture"};
217 cvar_t r_shadow_bouncegrid_lightpathsize = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_lightpathsize", "64", "radius (in game units) of the light path for accumulation of light in the bouncegrid texture"};
218 cvar_t r_shadow_bouncegrid_normalizevectors = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_normalizevectors", "1", "normalize random vectors (otherwise their length can vary, which dims the lighting further from the light)"};
219 cvar_t r_shadow_bouncegrid_particlebounceintensity = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_particlebounceintensity", "4", "amount of energy carried over after each bounce, this is a multiplier of texture color and the result is clamped to 1 or less, to prevent adding energy on each bounce"};
220 cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "1", "brightness of particles contributing to bouncegrid texture"};
221 cvar_t r_shadow_bouncegrid_rng_seed = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_rng_seed", "0", "0+ = use this number as RNG seed, -1 = use time instead for disco-like craziness in dynamic mode"};
222 cvar_t r_shadow_bouncegrid_rng_type = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_rng_type", "0", "0 = Lehmer 128bit RNG (slow but high quality), 1 = lhcheeserand 32bit RNG (quick)"};
223 cvar_t r_shadow_bouncegrid_static = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static", "1", "use static radiosity solution (high quality) rather than dynamic (splotchy)"};
224 cvar_t r_shadow_bouncegrid_static_bounceminimumintensity = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_bounceminimumintensity", "0.01", "stop bouncing once intensity drops below this fraction of the original particle color"};
225 cvar_t r_shadow_bouncegrid_static_directionalshading = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_directionalshading", "1", "whether to use directionalshading when in static mode"};
226 cvar_t r_shadow_bouncegrid_static_lightradiusscale = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_lightradiusscale", "5", "particles stop at this fraction of light radius (can be more than 1) when in static mode"};
227 cvar_t r_shadow_bouncegrid_static_maxbounce = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_maxbounce", "5", "maximum number of bounces for a particle (minimum is 0) in static mode"};
228 cvar_t r_shadow_bouncegrid_static_maxphotons = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_maxphotons", "250000", "upper bound on photons in static mode"};
229 cvar_t r_shadow_bouncegrid_static_quality = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_quality", "16", "amount of photons that should be fired (this is multiplied by spacing ^ 2 to make it adaptive with spacing changes)"};
230 cvar_t r_shadow_bouncegrid_static_spacing = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_static_spacing", "64", "unit size of bouncegrid pixel when in static mode"};
231 cvar_t r_shadow_bouncegrid_subsamples = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_subsamples", "1", "when generating the texture, sample this many points along each dimension (multisampling uses more compute but not more memory bandwidth)"};
232 cvar_t r_shadow_bouncegrid_threaded = {CVAR_CLIENT | CVAR_SAVE, "r_shadow_bouncegrid_threaded", "1", "enables use of taskqueue_maxthreads to perform the traces and slice rendering of bouncegrid"};
233 cvar_t r_coronas = {CVAR_CLIENT | CVAR_SAVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
234 cvar_t r_coronas_occlusionsizescale = {CVAR_CLIENT | CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
235 cvar_t r_coronas_occlusionquery = {CVAR_CLIENT | CVAR_SAVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility"};
236 cvar_t gl_flashblend = {CVAR_CLIENT | CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
237 cvar_t r_editlights = {CVAR_CLIENT, "r_editlights", "0", "enables .rtlights file editing mode"};
238 cvar_t r_editlights_cursordistance = {CVAR_CLIENT, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
239 cvar_t r_editlights_cursorpushback = {CVAR_CLIENT, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
240 cvar_t r_editlights_cursorpushoff = {CVAR_CLIENT, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
241 cvar_t r_editlights_cursorgrid = {CVAR_CLIENT, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
242 cvar_t r_editlights_quakelightsizescale = {CVAR_CLIENT | CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
243 cvar_t r_editlights_drawproperties = {CVAR_CLIENT, "r_editlights_drawproperties", "1", "draw properties of currently selected light"};
244 cvar_t r_editlights_current_origin = {CVAR_CLIENT, "r_editlights_current_origin", "0 0 0", "origin of selected light"};
245 cvar_t r_editlights_current_angles = {CVAR_CLIENT, "r_editlights_current_angles", "0 0 0", "angles of selected light"};
246 cvar_t r_editlights_current_color = {CVAR_CLIENT, "r_editlights_current_color", "1 1 1", "color of selected light"};
247 cvar_t r_editlights_current_radius = {CVAR_CLIENT, "r_editlights_current_radius", "0", "radius of selected light"};
248 cvar_t r_editlights_current_corona = {CVAR_CLIENT, "r_editlights_current_corona", "0", "corona intensity of selected light"};
249 cvar_t r_editlights_current_coronasize = {CVAR_CLIENT, "r_editlights_current_coronasize", "0", "corona size of selected light"};
250 cvar_t r_editlights_current_style = {CVAR_CLIENT, "r_editlights_current_style", "0", "style of selected light"};
251 cvar_t r_editlights_current_shadows = {CVAR_CLIENT, "r_editlights_current_shadows", "0", "shadows flag of selected light"};
252 cvar_t r_editlights_current_cubemap = {CVAR_CLIENT, "r_editlights_current_cubemap", "0", "cubemap of selected light"};
253 cvar_t r_editlights_current_ambient = {CVAR_CLIENT, "r_editlights_current_ambient", "0", "ambient intensity of selected light"};
254 cvar_t r_editlights_current_diffuse = {CVAR_CLIENT, "r_editlights_current_diffuse", "1", "diffuse intensity of selected light"};
255 cvar_t r_editlights_current_specular = {CVAR_CLIENT, "r_editlights_current_specular", "1", "specular intensity of selected light"};
256 cvar_t r_editlights_current_normalmode = {CVAR_CLIENT, "r_editlights_current_normalmode", "0", "normalmode flag of selected light"};
257 cvar_t r_editlights_current_realtimemode = {CVAR_CLIENT, "r_editlights_current_realtimemode", "0", "realtimemode flag of selected light"};
258
259 r_shadow_bouncegrid_state_t r_shadow_bouncegrid_state;
260
261 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
262 #define ATTENTABLESIZE 256
263 // 1D gradient, 2D circle and 3D sphere attenuation textures
264 #define ATTEN1DSIZE 32
265 #define ATTEN2DSIZE 64
266 #define ATTEN3DSIZE 32
267
268 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
269 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
270 static float r_shadow_attentable[ATTENTABLESIZE+1];
271
272 rtlight_t *r_shadow_compilingrtlight;
273 static memexpandablearray_t r_shadow_worldlightsarray;
274 dlight_t *r_shadow_selectedlight;
275 dlight_t r_shadow_bufferlight;
276 vec3_t r_editlights_cursorlocation;
277 qboolean r_editlights_lockcursor;
278
279 extern int con_vislines;
280
281 void R_Shadow_UncompileWorldLights(void);
282 void R_Shadow_ClearWorldLights(void);
283 void R_Shadow_SaveWorldLights(void);
284 void R_Shadow_LoadWorldLights(void);
285 void R_Shadow_LoadLightsFile(void);
286 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
287 void R_Shadow_EditLights_Reload_f(cmd_state_t *cmd);
288 static void R_Shadow_MakeTextures(void);
289
290 #define EDLIGHTSPRSIZE                  8
291 skinframe_t *r_editlights_sprcursor;
292 skinframe_t *r_editlights_sprlight;
293 skinframe_t *r_editlights_sprnoshadowlight;
294 skinframe_t *r_editlights_sprcubemaplight;
295 skinframe_t *r_editlights_sprcubemapnoshadowlight;
296 skinframe_t *r_editlights_sprselection;
297
298 static void R_Shadow_DrawModelShadowMaps(void);
299 static void R_Shadow_MakeShadowMap(int texturesize);
300 static void R_Shadow_MakeVSDCT(void);
301 static void R_Shadow_SetShadowMode(void)
302 {
303         r_shadow_shadowmode_shadowmapping = r_shadow_shadowmapping.integer;
304         r_shadow_shadowmode_deferred = r_shadow_deferred.integer;
305         r_shadow_shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
306         r_shadow_shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
307         r_shadow_shadowmapmaxsize = bound(r_shadow_shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, r_shadow_shadowmaptexturesize / 8);
308         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL32;
309         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
310         r_shadow_shadowmapshadowsampler = r_shadow_shadowmapping_useshadowsampler.integer != 0;
311         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
312         r_shadow_shadowmapsampler = false;
313         r_shadow_shadowmappcf = 0;
314         r_shadow_shadowmapdepthtexture = r_fb.usedepthtextures;
315         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_DISABLED;
316         if (r_shadow_shadowmode_shadowmapping || r_shadow_shadowmode_deferred)
317         {
318                 switch (vid.renderpath)
319                 {
320                 case RENDERPATH_GL32:
321                         if (r_shadow_shadowmapfilterquality < 0)
322                         {
323                                 if (!r_fb.usedepthtextures)
324                                         r_shadow_shadowmappcf = 1;
325                                 else if ((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && r_shadow_shadowmapshadowsampler)
326                                 {
327                                         r_shadow_shadowmapsampler = true;
328                                         r_shadow_shadowmappcf = 1;
329                                 }
330                                 else if (vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
331                                         r_shadow_shadowmappcf = 1;
332                                 else if ((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
333                                         r_shadow_shadowmappcf = 1;
334                                 else
335                                         r_shadow_shadowmapsampler = r_shadow_shadowmapshadowsampler;
336                         }
337                         else
338                         {
339                                 r_shadow_shadowmapsampler = r_shadow_shadowmapshadowsampler;
340                                 switch (r_shadow_shadowmapfilterquality)
341                                 {
342                                 case 1:
343                                         break;
344                                 case 2:
345                                         r_shadow_shadowmappcf = 1;
346                                         break;
347                                 case 3:
348                                         r_shadow_shadowmappcf = 1;
349                                         break;
350                                 case 4:
351                                         r_shadow_shadowmappcf = 2;
352                                         break;
353                                 }
354                         }
355                         if (!r_fb.usedepthtextures)
356                                 r_shadow_shadowmapsampler = false;
357                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
358                         break;
359                 case RENDERPATH_GLES2:
360                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
361                         break;
362                 }
363         }
364
365         switch (r_shadow_shadowmode)
366         {
367         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
368                 Mod_AllocLightmap_Init(&r_shadow_shadowmapatlas_state, r_main_mempool, r_shadow_shadowmaptexturesize, r_shadow_shadowmaptexturesize);
369                 break;
370         case R_SHADOW_SHADOWMODE_DISABLED:
371                 break;
372         }
373
374         if(R_CompileShader_CheckStaticParms())
375                 R_GLSL_Restart_f(&cmd_client);
376 }
377
378 qboolean R_Shadow_ShadowMappingEnabled(void)
379 {
380         switch (r_shadow_shadowmode)
381         {
382         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
383                 return true;
384         case R_SHADOW_SHADOWMODE_DISABLED:
385                 return false;
386         }
387         return false;
388 }
389
390 static void R_Shadow_FreeShadowMaps(void)
391 {
392         R_Shadow_UncompileWorldLights();
393
394         Mod_AllocLightmap_Free(&r_shadow_shadowmapatlas_state);
395
396         R_Shadow_SetShadowMode();
397
398         R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d);
399
400         r_shadow_fbo2d = 0;
401
402         if (r_shadow_shadowmap2ddepthtexture)
403                 R_FreeTexture(r_shadow_shadowmap2ddepthtexture);
404         r_shadow_shadowmap2ddepthtexture = NULL;
405
406         if (r_shadow_shadowmap2ddepthbuffer)
407                 R_FreeTexture(r_shadow_shadowmap2ddepthbuffer);
408         r_shadow_shadowmap2ddepthbuffer = NULL;
409
410         if (r_shadow_shadowmapvsdcttexture)
411                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
412         r_shadow_shadowmapvsdcttexture = NULL;
413
414 }
415
416 static void r_shadow_start(void)
417 {
418         // allocate vertex processing arrays
419         memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state));
420         r_shadow_attenuationgradienttexture = NULL;
421         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_DISABLED;
422         r_shadow_shadowmap2ddepthtexture = NULL;
423         r_shadow_shadowmap2ddepthbuffer = NULL;
424         r_shadow_shadowmapvsdcttexture = NULL;
425         r_shadow_shadowmapmaxsize = 0;
426         r_shadow_shadowmaptexturesize = 0;
427         r_shadow_shadowmapfilterquality = -1;
428         r_shadow_shadowmapdepthbits = 0;
429         r_shadow_shadowmapvsdct = false;
430         r_shadow_shadowmapsampler = false;
431         r_shadow_shadowmappcf = 0;
432         r_shadow_fbo2d = 0;
433
434         R_Shadow_FreeShadowMaps();
435
436         r_shadow_texturepool = NULL;
437         r_shadow_filters_texturepool = NULL;
438         R_Shadow_MakeTextures();
439         r_shadow_scenemaxlights = 0;
440         r_shadow_scenenumlights = 0;
441         r_shadow_scenelightlist = NULL;
442         maxshadowtriangles = 0;
443         shadowelements = NULL;
444         maxshadowvertices = 0;
445         shadowvertex3f = NULL;
446         maxvertexupdate = 0;
447         vertexupdate = NULL;
448         vertexremap = NULL;
449         vertexupdatenum = 0;
450         maxshadowmark = 0;
451         numshadowmark = 0;
452         shadowmark = NULL;
453         shadowmarklist = NULL;
454         shadowmarkcount = 0;
455         maxshadowsides = 0;
456         numshadowsides = 0;
457         shadowsides = NULL;
458         shadowsideslist = NULL;
459         r_shadow_buffer_numleafpvsbytes = 0;
460         r_shadow_buffer_visitingleafpvs = NULL;
461         r_shadow_buffer_leafpvs = NULL;
462         r_shadow_buffer_leaflist = NULL;
463         r_shadow_buffer_numsurfacepvsbytes = 0;
464         r_shadow_buffer_surfacepvs = NULL;
465         r_shadow_buffer_surfacelist = NULL;
466         r_shadow_buffer_surfacesides = NULL;
467         r_shadow_buffer_numshadowtrispvsbytes = 0;
468         r_shadow_buffer_shadowtrispvs = NULL;
469         r_shadow_buffer_numlighttrispvsbytes = 0;
470         r_shadow_buffer_lighttrispvs = NULL;
471
472         r_shadow_usingdeferredprepass = false;
473         r_shadow_prepass_width = r_shadow_prepass_height = 0;
474
475         // determine renderpath specific capabilities, we don't need to figure
476         // these out per frame...
477         switch(vid.renderpath)
478         {
479         case RENDERPATH_GL32:
480                 r_shadow_bouncegrid_state.allowdirectionalshading = true;
481                 r_shadow_bouncegrid_state.capable = true;
482                 break;
483         case RENDERPATH_GLES2:
484                 // for performance reasons, do not use directional shading on GLES devices
485                 r_shadow_bouncegrid_state.capable = true;
486                 break;
487         }
488 }
489
490 static void R_Shadow_FreeDeferred(void);
491 static void r_shadow_shutdown(void)
492 {
493         CHECKGLERROR
494
495         R_Shadow_FreeShadowMaps();
496
497         r_shadow_usingdeferredprepass = false;
498         if (r_shadow_prepass_width)
499                 R_Shadow_FreeDeferred();
500         r_shadow_prepass_width = r_shadow_prepass_height = 0;
501
502         CHECKGLERROR
503         r_shadow_scenemaxlights = 0;
504         r_shadow_scenenumlights = 0;
505         if (r_shadow_scenelightlist)
506                 Mem_Free(r_shadow_scenelightlist);
507         r_shadow_scenelightlist = NULL;
508         r_shadow_bouncegrid_state.highpixels = NULL;
509         if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
510         if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
511         if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
512         if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
513         if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
514         if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
515         if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
516         memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state));
517         r_shadow_attenuationgradienttexture = NULL;
518         R_FreeTexturePool(&r_shadow_texturepool);
519         R_FreeTexturePool(&r_shadow_filters_texturepool);
520         maxshadowtriangles = 0;
521         if (shadowelements)
522                 Mem_Free(shadowelements);
523         shadowelements = NULL;
524         if (shadowvertex3f)
525                 Mem_Free(shadowvertex3f);
526         shadowvertex3f = NULL;
527         maxvertexupdate = 0;
528         if (vertexupdate)
529                 Mem_Free(vertexupdate);
530         vertexupdate = NULL;
531         if (vertexremap)
532                 Mem_Free(vertexremap);
533         vertexremap = NULL;
534         vertexupdatenum = 0;
535         maxshadowmark = 0;
536         numshadowmark = 0;
537         if (shadowmark)
538                 Mem_Free(shadowmark);
539         shadowmark = NULL;
540         if (shadowmarklist)
541                 Mem_Free(shadowmarklist);
542         shadowmarklist = NULL;
543         shadowmarkcount = 0;
544         maxshadowsides = 0;
545         numshadowsides = 0;
546         if (shadowsides)
547                 Mem_Free(shadowsides);
548         shadowsides = NULL;
549         if (shadowsideslist)
550                 Mem_Free(shadowsideslist);
551         shadowsideslist = NULL;
552         r_shadow_buffer_numleafpvsbytes = 0;
553         if (r_shadow_buffer_visitingleafpvs)
554                 Mem_Free(r_shadow_buffer_visitingleafpvs);
555         r_shadow_buffer_visitingleafpvs = NULL;
556         if (r_shadow_buffer_leafpvs)
557                 Mem_Free(r_shadow_buffer_leafpvs);
558         r_shadow_buffer_leafpvs = NULL;
559         if (r_shadow_buffer_leaflist)
560                 Mem_Free(r_shadow_buffer_leaflist);
561         r_shadow_buffer_leaflist = NULL;
562         r_shadow_buffer_numsurfacepvsbytes = 0;
563         if (r_shadow_buffer_surfacepvs)
564                 Mem_Free(r_shadow_buffer_surfacepvs);
565         r_shadow_buffer_surfacepvs = NULL;
566         if (r_shadow_buffer_surfacelist)
567                 Mem_Free(r_shadow_buffer_surfacelist);
568         r_shadow_buffer_surfacelist = NULL;
569         if (r_shadow_buffer_surfacesides)
570                 Mem_Free(r_shadow_buffer_surfacesides);
571         r_shadow_buffer_surfacesides = NULL;
572         r_shadow_buffer_numshadowtrispvsbytes = 0;
573         if (r_shadow_buffer_shadowtrispvs)
574                 Mem_Free(r_shadow_buffer_shadowtrispvs);
575         r_shadow_buffer_numlighttrispvsbytes = 0;
576         if (r_shadow_buffer_lighttrispvs)
577                 Mem_Free(r_shadow_buffer_lighttrispvs);
578 }
579
580 static void r_shadow_newmap(void)
581 {
582         r_shadow_bouncegrid_state.highpixels = NULL;
583         if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
584         if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
585         if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
586         if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
587         if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
588         if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
589         if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
590
591         if (r_shadow_bouncegrid_state.texture)    { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
592         if (r_shadow_lightcorona)                 { R_SkinFrame_MarkUsed(r_shadow_lightcorona); }
593         if (r_editlights_sprcursor)               { R_SkinFrame_MarkUsed(r_editlights_sprcursor); }
594         if (r_editlights_sprlight)                { R_SkinFrame_MarkUsed(r_editlights_sprlight); }
595         if (r_editlights_sprnoshadowlight)        { R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight); }
596         if (r_editlights_sprcubemaplight)         { R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight); }
597         if (r_editlights_sprcubemapnoshadowlight) { R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight); }
598         if (r_editlights_sprselection)            { R_SkinFrame_MarkUsed(r_editlights_sprselection); }
599         if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
600                 R_Shadow_EditLights_Reload_f(&cmd_client);
601 }
602
603 void R_Shadow_Init(void)
604 {
605         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
606         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
607         Cvar_RegisterVariable(&r_shadow_usebihculling);
608         Cvar_RegisterVariable(&r_shadow_usenormalmap);
609         Cvar_RegisterVariable(&r_shadow_debuglight);
610         Cvar_RegisterVariable(&r_shadow_deferred);
611         Cvar_RegisterVariable(&r_shadow_gloss);
612         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
613         Cvar_RegisterVariable(&r_shadow_glossintensity);
614         Cvar_RegisterVariable(&r_shadow_glossexponent);
615         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
616         Cvar_RegisterVariable(&r_shadow_glossexact);
617         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
618         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
619         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
620         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
621         Cvar_RegisterVariable(&r_shadow_projectdistance);
622         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
623         Cvar_RegisterVariable(&r_shadow_realtime_world_importlightentitiesfrommap);
624         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
625         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
626         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
627         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
628         Cvar_RegisterVariable(&r_shadow_realtime_world);
629         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
630         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
631         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
632         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
633         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
634         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
635         Cvar_RegisterVariable(&r_shadow_scissor);
636         Cvar_RegisterVariable(&r_shadow_shadowmapping);
637         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
638         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
639         Cvar_RegisterVariable(&r_shadow_shadowmapping_useshadowsampler);
640         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
641         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
642         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
643         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
644         Cvar_RegisterVariable(&r_shadow_shadowmapping_texturesize);
645 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
646 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
647         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
648         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
649         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
650         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
651         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
652         Cvar_RegisterVariable(&r_shadow_sortsurfaces);
653         Cvar_RegisterVariable(&r_shadow_culllights_pvs);
654         Cvar_RegisterVariable(&r_shadow_culllights_trace);
655         Cvar_RegisterVariable(&r_shadow_culllights_trace_eyejitter);
656         Cvar_RegisterVariable(&r_shadow_culllights_trace_enlarge);
657         Cvar_RegisterVariable(&r_shadow_culllights_trace_expand);
658         Cvar_RegisterVariable(&r_shadow_culllights_trace_pad);
659         Cvar_RegisterVariable(&r_shadow_culllights_trace_samples);
660         Cvar_RegisterVariable(&r_shadow_culllights_trace_tempsamples);
661         Cvar_RegisterVariable(&r_shadow_culllights_trace_delay);
662         Cvar_RegisterVariable(&r_shadow_bouncegrid);
663         Cvar_RegisterVariable(&r_shadow_bouncegrid_blur);
664         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_bounceminimumintensity);
665         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_culllightpaths);
666         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_directionalshading);
667         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_dlightparticlemultiplier);
668         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_hitmodels);
669         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_lightradiusscale);
670         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_maxbounce);
671         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_maxphotons);
672         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_quality);
673         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_spacing);
674         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_updateinterval);
675         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_x);
676         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_y);
677         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_z);
678         Cvar_RegisterVariable(&r_shadow_bouncegrid_floatcolors);
679         Cvar_RegisterVariable(&r_shadow_bouncegrid_includedirectlighting);
680         Cvar_RegisterVariable(&r_shadow_bouncegrid_intensity);
681         Cvar_RegisterVariable(&r_shadow_bouncegrid_lightpathsize);
682         Cvar_RegisterVariable(&r_shadow_bouncegrid_normalizevectors);
683         Cvar_RegisterVariable(&r_shadow_bouncegrid_particlebounceintensity);
684         Cvar_RegisterVariable(&r_shadow_bouncegrid_particleintensity);
685         Cvar_RegisterVariable(&r_shadow_bouncegrid_rng_seed);
686         Cvar_RegisterVariable(&r_shadow_bouncegrid_rng_type);
687         Cvar_RegisterVariable(&r_shadow_bouncegrid_static);
688         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_bounceminimumintensity);
689         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_directionalshading);
690         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_lightradiusscale);
691         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxbounce);
692         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxphotons);
693         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_quality);
694         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_spacing);
695         Cvar_RegisterVariable(&r_shadow_bouncegrid_subsamples);
696         Cvar_RegisterVariable(&r_shadow_bouncegrid_threaded);
697         Cvar_RegisterVariable(&r_coronas);
698         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
699         Cvar_RegisterVariable(&r_coronas_occlusionquery);
700         Cvar_RegisterVariable(&gl_flashblend);
701         R_Shadow_EditLights_Init();
702         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
703         r_shadow_scenemaxlights = 0;
704         r_shadow_scenenumlights = 0;
705         r_shadow_scenelightlist = NULL;
706         maxshadowtriangles = 0;
707         shadowelements = NULL;
708         maxshadowvertices = 0;
709         shadowvertex3f = NULL;
710         maxvertexupdate = 0;
711         vertexupdate = NULL;
712         vertexremap = NULL;
713         vertexupdatenum = 0;
714         maxshadowmark = 0;
715         numshadowmark = 0;
716         shadowmark = NULL;
717         shadowmarklist = NULL;
718         shadowmarkcount = 0;
719         maxshadowsides = 0;
720         numshadowsides = 0;
721         shadowsides = NULL;
722         shadowsideslist = NULL;
723         r_shadow_buffer_numleafpvsbytes = 0;
724         r_shadow_buffer_visitingleafpvs = NULL;
725         r_shadow_buffer_leafpvs = NULL;
726         r_shadow_buffer_leaflist = NULL;
727         r_shadow_buffer_numsurfacepvsbytes = 0;
728         r_shadow_buffer_surfacepvs = NULL;
729         r_shadow_buffer_surfacelist = NULL;
730         r_shadow_buffer_surfacesides = NULL;
731         r_shadow_buffer_shadowtrispvs = NULL;
732         r_shadow_buffer_lighttrispvs = NULL;
733         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap, NULL, NULL);
734 }
735
736 matrix4x4_t matrix_attenuationxyz =
737 {
738         {
739                 {0.5, 0.0, 0.0, 0.5},
740                 {0.0, 0.5, 0.0, 0.5},
741                 {0.0, 0.0, 0.5, 0.5},
742                 {0.0, 0.0, 0.0, 1.0}
743         }
744 };
745
746 matrix4x4_t matrix_attenuationz =
747 {
748         {
749                 {0.0, 0.0, 0.5, 0.5},
750                 {0.0, 0.0, 0.0, 0.5},
751                 {0.0, 0.0, 0.0, 0.5},
752                 {0.0, 0.0, 0.0, 1.0}
753         }
754 };
755
756 static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
757 {
758         numvertices = ((numvertices + 255) & ~255) * vertscale;
759         numtriangles = ((numtriangles + 255) & ~255) * triscale;
760         // make sure shadowelements is big enough for this volume
761         if (maxshadowtriangles < numtriangles)
762         {
763                 maxshadowtriangles = numtriangles;
764                 if (shadowelements)
765                         Mem_Free(shadowelements);
766                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
767         }
768         // make sure shadowvertex3f is big enough for this volume
769         if (maxshadowvertices < numvertices)
770         {
771                 maxshadowvertices = numvertices;
772                 if (shadowvertex3f)
773                         Mem_Free(shadowvertex3f);
774                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
775         }
776 }
777
778 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
779 {
780         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
781         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
782         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
783         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
784         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
785         {
786                 if (r_shadow_buffer_visitingleafpvs)
787                         Mem_Free(r_shadow_buffer_visitingleafpvs);
788                 if (r_shadow_buffer_leafpvs)
789                         Mem_Free(r_shadow_buffer_leafpvs);
790                 if (r_shadow_buffer_leaflist)
791                         Mem_Free(r_shadow_buffer_leaflist);
792                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
793                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
794                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
795                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
796         }
797         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
798         {
799                 if (r_shadow_buffer_surfacepvs)
800                         Mem_Free(r_shadow_buffer_surfacepvs);
801                 if (r_shadow_buffer_surfacelist)
802                         Mem_Free(r_shadow_buffer_surfacelist);
803                 if (r_shadow_buffer_surfacesides)
804                         Mem_Free(r_shadow_buffer_surfacesides);
805                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
806                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
807                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
808                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
809         }
810         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
811         {
812                 if (r_shadow_buffer_shadowtrispvs)
813                         Mem_Free(r_shadow_buffer_shadowtrispvs);
814                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
815                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
816         }
817         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
818         {
819                 if (r_shadow_buffer_lighttrispvs)
820                         Mem_Free(r_shadow_buffer_lighttrispvs);
821                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
822                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
823         }
824 }
825
826 void R_Shadow_PrepareShadowMark(int numtris)
827 {
828         // make sure shadowmark is big enough for this volume
829         if (maxshadowmark < numtris)
830         {
831                 maxshadowmark = numtris;
832                 if (shadowmark)
833                         Mem_Free(shadowmark);
834                 if (shadowmarklist)
835                         Mem_Free(shadowmarklist);
836                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
837                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
838                 shadowmarkcount = 0;
839         }
840         shadowmarkcount++;
841         // if shadowmarkcount wrapped we clear the array and adjust accordingly
842         if (shadowmarkcount == 0)
843         {
844                 shadowmarkcount = 1;
845                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
846         }
847         numshadowmark = 0;
848 }
849
850 void R_Shadow_PrepareShadowSides(int numtris)
851 {
852         if (maxshadowsides < numtris)
853         {
854                 maxshadowsides = numtris;
855                 if (shadowsides)
856                         Mem_Free(shadowsides);
857                 if (shadowsideslist)
858                         Mem_Free(shadowsideslist);
859                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
860                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
861         }
862         numshadowsides = 0;
863 }
864
865 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
866 {
867         // p1, p2, p3 are in the cubemap's local coordinate system
868         // bias = border/(size - border)
869         int mask = 0x3F;
870
871         float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
872                   dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
873                   dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
874         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
875                 mask &= (3<<4)
876                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
877                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
878                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
879         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
880                 mask &= (3<<4)
881                         | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
882                         | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))                    
883                         | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
884
885         dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
886         dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
887         dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
888         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
889                 mask &= (3<<0)
890                         | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
891                         | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))                    
892                         | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
893         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
894                 mask &= (3<<0)
895                         | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
896                         | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
897                         | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
898
899         dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
900         dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
901         dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
902         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
903                 mask &= (3<<2)
904                         | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
905                         | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
906                         | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
907         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
908                 mask &= (3<<2)
909                         | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
910                         | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
911                         | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
912
913         return mask;
914 }
915
916 static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
917 {
918         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
919         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
920         int mask = 0x3F;
921
922         VectorSubtract(maxs, mins, radius);
923         VectorScale(radius, 0.5f, radius);
924         VectorAdd(mins, radius, center);
925         Matrix4x4_Transform(worldtolight, center, lightcenter);
926         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
927         VectorSubtract(lightcenter, lightradius, pmin);
928         VectorAdd(lightcenter, lightradius, pmax);
929
930         dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
931         dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
932         if(ap1 > bias*an1 && ap2 > bias*an2)
933                 mask &= (3<<4)
934                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
935                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
936         if(an1 > bias*ap1 && an2 > bias*ap2)
937                 mask &= (3<<4)
938                         | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
939                         | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
940
941         dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
942         dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
943         if(ap1 > bias*an1 && ap2 > bias*an2)
944                 mask &= (3<<0)
945                         | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
946                         | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
947         if(an1 > bias*ap1 && an2 > bias*ap2)
948                 mask &= (3<<0)
949                         | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
950                         | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
951
952         dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
953         dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
954         if(ap1 > bias*an1 && ap2 > bias*an2)
955                 mask &= (3<<2)
956                         | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
957                         | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
958         if(an1 > bias*ap1 && an2 > bias*ap2)
959                 mask &= (3<<2)
960                         | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
961                         | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
962
963         return mask;
964 }
965
966 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
967
968 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
969 {
970         // p is in the cubemap's local coordinate system
971         // bias = border/(size - border)
972         float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
973         float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
974         float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
975         int mask = 0x3F;
976         if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
977         if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
978         if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
979         if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
980         if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
981         if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
982         return mask;
983 }
984
985 static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
986 {
987         int i;
988         vec3_t o, p, n;
989         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
990         float scale = (size - 2*border)/size, len;
991         float bias = border / (float)(size - border), dp, dn, ap, an;
992         // check if cone enclosing side would cross frustum plane
993         scale = 2 / (scale*scale + 2);
994         Matrix4x4_OriginFromMatrix(&rtlight->matrix_lighttoworld, o);
995         for (i = 0;i < 5;i++)
996         {
997                 if (PlaneDiff(o, &r_refdef.view.frustum[i]) > -0.03125)
998                         continue;
999                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1000                 len = scale*VectorLength2(n);
1001                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1002                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1003                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1004         }
1005         if (PlaneDiff(o, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1006         {
1007                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1008                 len = scale*VectorLength2(n);
1009                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1010                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1011                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1012         }
1013         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1014         // check if frustum corners/origin cross plane sides
1015 #if 1
1016         // infinite version, assumes frustum corners merely give direction and extend to infinite distance
1017         Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
1018         dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1019         masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1020         masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1021         dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1022         masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1023         masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1024         dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1025         masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1026         masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1027         for (i = 0;i < 4;i++)
1028         {
1029                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
1030                 VectorSubtract(n, p, n);
1031                 dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
1032                 if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
1033                 if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
1034                 dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
1035                 if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
1036                 if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
1037                 dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
1038                 if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
1039                 if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
1040         }
1041 #else
1042         // finite version, assumes corners are a finite distance from origin dependent on far plane
1043         for (i = 0;i < 5;i++)
1044         {
1045                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1046                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1047                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1048                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1049                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1050                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1051                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1052                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1053                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1054                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1055         }
1056 #endif
1057         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1058 }
1059
1060 int R_Shadow_ChooseSidesFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const matrix4x4_t *worldtolight, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs, int *totals)
1061 {
1062         int t, tend;
1063         const int *e;
1064         const float *v[3];
1065         float normal[3];
1066         vec3_t p[3];
1067         float bias;
1068         int mask, surfacemask = 0;
1069         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1070                 return 0;
1071         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1072         tend = firsttriangle + numtris;
1073         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1074         {
1075                 // surface box entirely inside light box, no box cull
1076                 if (projectdirection)
1077                 {
1078                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1079                         {
1080                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1081                                 TriangleNormal(v[0], v[1], v[2], normal);
1082                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1083                                 {
1084                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1085                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1086                                         surfacemask |= mask;
1087                                         if(totals)
1088                                         {
1089                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1090                                                 shadowsides[numshadowsides] = mask;
1091                                                 shadowsideslist[numshadowsides++] = t;
1092                                         }
1093                                 }
1094                         }
1095                 }
1096                 else
1097                 {
1098                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1099                         {
1100                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1101                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1102                                 {
1103                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1104                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1105                                         surfacemask |= mask;
1106                                         if(totals)
1107                                         {
1108                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1109                                                 shadowsides[numshadowsides] = mask;
1110                                                 shadowsideslist[numshadowsides++] = t;
1111                                         }
1112                                 }
1113                         }
1114                 }
1115         }
1116         else
1117         {
1118                 // surface box not entirely inside light box, cull each triangle
1119                 if (projectdirection)
1120                 {
1121                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1122                         {
1123                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1124                                 TriangleNormal(v[0], v[1], v[2], normal);
1125                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1126                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1127                                 {
1128                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1129                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1130                                         surfacemask |= mask;
1131                                         if(totals)
1132                                         {
1133                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1134                                                 shadowsides[numshadowsides] = mask;
1135                                                 shadowsideslist[numshadowsides++] = t;
1136                                         }
1137                                 }
1138                         }
1139                 }
1140                 else
1141                 {
1142                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1143                         {
1144                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1145                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1146                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1147                                 {
1148                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1149                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1150                                         surfacemask |= mask;
1151                                         if(totals)
1152                                         {
1153                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1154                                                 shadowsides[numshadowsides] = mask;
1155                                                 shadowsideslist[numshadowsides++] = t;
1156                                         }
1157                                 }
1158                         }
1159                 }
1160         }
1161         return surfacemask;
1162 }
1163
1164 void R_Shadow_ShadowMapFromList(int numverts, int numtris, const float *vertex3f, const int *elements, int numsidetris, const int *sidetotals, const unsigned char *sides, const int *sidetris)
1165 {
1166         int i, j, outtriangles = 0;
1167         int *outelement3i[6];
1168         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1169                 return;
1170         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1171         // make sure shadowelements is big enough for this mesh
1172         if (maxshadowtriangles < outtriangles)
1173                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1174
1175         // compute the offset and size of the separate index lists for each cubemap side
1176         outtriangles = 0;
1177         for (i = 0;i < 6;i++)
1178         {
1179                 outelement3i[i] = shadowelements + outtriangles * 3;
1180                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1181                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1182                 outtriangles += sidetotals[i];
1183         }
1184
1185         // gather up the (sparse) triangles into separate index lists for each cubemap side
1186         for (i = 0;i < numsidetris;i++)
1187         {
1188                 const int *element = elements + sidetris[i] * 3;
1189                 for (j = 0;j < 6;j++)
1190                 {
1191                         if (sides[i] & (1 << j))
1192                         {
1193                                 outelement3i[j][0] = element[0];
1194                                 outelement3i[j][1] = element[1];
1195                                 outelement3i[j][2] = element[2];
1196                                 outelement3i[j] += 3;
1197                         }
1198                 }
1199         }
1200
1201         Mod_ShadowMesh_AddMesh(r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, vertex3f, outtriangles, shadowelements);
1202 }
1203
1204 static void R_Shadow_MakeTextures_MakeCorona(void)
1205 {
1206         float dx, dy;
1207         int x, y, a;
1208         unsigned char pixels[32][32][4];
1209         for (y = 0;y < 32;y++)
1210         {
1211                 dy = (y - 15.5f) * (1.0f / 16.0f);
1212                 for (x = 0;x < 32;x++)
1213                 {
1214                         dx = (x - 15.5f) * (1.0f / 16.0f);
1215                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1216                         a = bound(0, a, 255);
1217                         pixels[y][x][0] = a;
1218                         pixels[y][x][1] = a;
1219                         pixels[y][x][2] = a;
1220                         pixels[y][x][3] = 255;
1221                 }
1222         }
1223         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32, 0, 0, 0, false);
1224 }
1225
1226 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1227 {
1228         float dist = sqrt(x*x+y*y+z*z);
1229         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1230         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1231         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1232 }
1233
1234 static void R_Shadow_MakeTextures(void)
1235 {
1236         int x;
1237         float intensity, dist;
1238         unsigned int *data;
1239         R_Shadow_FreeShadowMaps();
1240         R_FreeTexturePool(&r_shadow_texturepool);
1241         r_shadow_texturepool = R_AllocTexturePool();
1242         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1243         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1244         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1245         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1246         for (x = 0;x <= ATTENTABLESIZE;x++)
1247         {
1248                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1249                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1250                 r_shadow_attentable[x] = bound(0, intensity, 1);
1251         }
1252         // 1D gradient texture
1253         for (x = 0;x < ATTEN1DSIZE;x++)
1254                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1255         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1256         Mem_Free(data);
1257
1258         R_Shadow_MakeTextures_MakeCorona();
1259
1260         // Editor light sprites
1261         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1262         "................"
1263         ".3............3."
1264         "..5...2332...5.."
1265         "...7.3....3.7..."
1266         "....7......7...."
1267         "...3.7....7.3..."
1268         "..2...7..7...2.."
1269         "..3..........3.."
1270         "..3..........3.."
1271         "..2...7..7...2.."
1272         "...3.7....7.3..."
1273         "....7......7...."
1274         "...7.3....3.7..."
1275         "..5...2332...5.."
1276         ".3............3."
1277         "................"
1278         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1279         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1280         "................"
1281         "................"
1282         "......1111......"
1283         "....11233211...."
1284         "...1234554321..."
1285         "...1356776531..."
1286         "..124677776421.."
1287         "..135777777531.."
1288         "..135777777531.."
1289         "..124677776421.."
1290         "...1356776531..."
1291         "...1234554321..."
1292         "....11233211...."
1293         "......1111......"
1294         "................"
1295         "................"
1296         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1297         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1298         "................"
1299         "................"
1300         "......1111......"
1301         "....11233211...."
1302         "...1234554321..."
1303         "...1356226531..."
1304         "..12462..26421.."
1305         "..1352....2531.."
1306         "..1352....2531.."
1307         "..12462..26421.."
1308         "...1356226531..."
1309         "...1234554321..."
1310         "....11233211...."
1311         "......1111......"
1312         "................"
1313         "................"
1314         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1315         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1316         "................"
1317         "................"
1318         "......2772......"
1319         "....27755772...."
1320         "..277533335772.."
1321         "..753333333357.."
1322         "..777533335777.."
1323         "..735775577537.."
1324         "..733357753337.."
1325         "..733337733337.."
1326         "..753337733357.."
1327         "..277537735772.."
1328         "....27777772...."
1329         "......2772......"
1330         "................"
1331         "................"
1332         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1333         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1334         "................"
1335         "................"
1336         "......2772......"
1337         "....27722772...."
1338         "..2772....2772.."
1339         "..72........27.."
1340         "..7772....2777.."
1341         "..7.27722772.7.."
1342         "..7...2772...7.."
1343         "..7....77....7.."
1344         "..72...77...27.."
1345         "..2772.77.2772.."
1346         "....27777772...."
1347         "......2772......"
1348         "................"
1349         "................"
1350         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1351         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1352         "................"
1353         ".777752..257777."
1354         ".742........247."
1355         ".72..........27."
1356         ".7............7."
1357         ".5............5."
1358         ".2............2."
1359         "................"
1360         "................"
1361         ".2............2."
1362         ".5............5."
1363         ".7............7."
1364         ".72..........27."
1365         ".742........247."
1366         ".777752..257777."
1367         "................"
1368         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1369 }
1370
1371 void R_Shadow_RenderMode_Begin(void)
1372 {
1373 #if 0
1374         GLint drawbuffer;
1375         GLint readbuffer;
1376 #endif
1377
1378         if (r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1379          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1380                 R_Shadow_MakeTextures();
1381
1382         CHECKGLERROR
1383         R_Mesh_ResetTextureState();
1384         GL_BlendFunc(GL_ONE, GL_ZERO);
1385         GL_DepthRange(0, 1);
1386         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1387         GL_DepthTest(true);
1388         GL_DepthMask(false);
1389         GL_Color(0, 0, 0, 1);
1390         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1391         
1392         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1393         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1394
1395         CHECKGLERROR
1396 #if 0
1397         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1398         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1399         r_shadow_drawbuffer = drawbuffer;
1400         r_shadow_readbuffer = readbuffer;
1401 #endif
1402         r_shadow_cullface_front = r_refdef.view.cullface_front;
1403         r_shadow_cullface_back = r_refdef.view.cullface_back;
1404 }
1405
1406 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
1407 {
1408         rsurface.rtlight = rtlight;
1409 }
1410
1411 void R_Shadow_RenderMode_Reset(void)
1412 {
1413         R_Mesh_ResetTextureState();
1414         R_Mesh_SetRenderTargets(r_shadow_viewfbo, r_shadow_viewdepthtexture, r_shadow_viewcolortexture, NULL, NULL, NULL);
1415         R_SetViewport(&r_refdef.view.viewport);
1416         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
1417         GL_DepthRange(0, 1);
1418         GL_DepthTest(true);
1419         GL_DepthMask(false);
1420         GL_DepthFunc(GL_LEQUAL);
1421         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1422         r_refdef.view.cullface_front = r_shadow_cullface_front;
1423         r_refdef.view.cullface_back = r_shadow_cullface_back;
1424         GL_CullFace(r_refdef.view.cullface_back);
1425         GL_Color(1, 1, 1, 1);
1426         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
1427         GL_BlendFunc(GL_ONE, GL_ZERO);
1428         R_SetupShader_Generic_NoTexture(false, false);
1429         r_shadow_usingshadowmap2d = false;
1430 }
1431
1432 void R_Shadow_ClearStencil(void)
1433 {
1434         GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 0);
1435         r_refdef.stats[r_stat_lights_clears]++;
1436 }
1437
1438 static void R_Shadow_MakeVSDCT(void)
1439 {
1440         // maps to a 2x3 texture rectangle with normalized coordinates
1441         // +-
1442         // XX
1443         // YY
1444         // ZZ
1445         // stores abs(dir.xy), offset.xy/2.5
1446         unsigned char data[4*6] =
1447         {
1448                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
1449                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
1450                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
1451                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
1452                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
1453                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
1454         };
1455         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
1456 }
1457
1458 static void R_Shadow_MakeShadowMap(int texturesize)
1459 {
1460         switch (r_shadow_shadowmode)
1461         {
1462         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
1463                 if (r_shadow_shadowmap2ddepthtexture) return;
1464                 if (r_fb.usedepthtextures)
1465                 {
1466                         r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", texturesize, texturesize, r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), r_shadow_shadowmapsampler);
1467                         r_shadow_shadowmap2ddepthbuffer = NULL;
1468                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
1469                 }
1470                 else
1471                 {
1472                         r_shadow_shadowmap2ddepthtexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", texturesize, texturesize, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
1473                         r_shadow_shadowmap2ddepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "shadowmap", texturesize, texturesize, r_shadow_shadowmapdepthbits >= 24 ? TEXTYPE_DEPTHBUFFER24 : TEXTYPE_DEPTHBUFFER16);
1474                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
1475                 }
1476                 break;
1477         case R_SHADOW_SHADOWMODE_DISABLED:
1478                 break;
1479         }
1480 }
1481
1482 void R_Shadow_ClearShadowMapTexture(void)
1483 {
1484         r_viewport_t viewport;
1485         float clearcolor[4];
1486
1487         // if they don't exist, create our textures now
1488         if (!r_shadow_shadowmap2ddepthtexture)
1489                 R_Shadow_MakeShadowMap(r_shadow_shadowmaptexturesize);
1490         if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
1491                 R_Shadow_MakeVSDCT();
1492
1493         // we're setting up to render shadowmaps, so change rendermode
1494         r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
1495
1496         R_Mesh_ResetTextureState();
1497         R_Shadow_RenderMode_Reset();
1498         if (r_shadow_shadowmap2ddepthbuffer)
1499                 R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
1500         else
1501                 R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
1502         R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
1503         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
1504         GL_DepthMask(true);
1505         GL_DepthTest(true);
1506
1507         // we have to set a viewport to clear anything in some renderpaths (D3D)
1508         R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, r_shadow_shadowmaptexturesize, r_shadow_shadowmaptexturesize, 0, 0, 1.0, 1.0, 0.001f, 1.0f, NULL);
1509         R_SetViewport(&viewport);
1510         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
1511         if (r_shadow_shadowmap2ddepthbuffer)
1512                 GL_ColorMask(1, 1, 1, 1);
1513         else
1514                 GL_ColorMask(0, 0, 0, 0);
1515         switch (vid.renderpath)
1516         {
1517         case RENDERPATH_GL32:
1518         case RENDERPATH_GLES2:
1519                 GL_CullFace(r_refdef.view.cullface_back);
1520                 break;
1521         }
1522         Vector4Set(clearcolor, 1, 1, 1, 1);
1523         if (r_shadow_shadowmap2ddepthbuffer)
1524                 GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
1525         else
1526                 GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
1527 }
1528
1529 static void R_Shadow_SetShadowmapParametersForLight(qboolean noselfshadowpass)
1530 {
1531         int size = rsurface.rtlight->shadowmapatlassidesize;
1532         float nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
1533         float farclip = 1.0f;
1534         float bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
1535         r_shadow_lightshadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
1536         r_shadow_lightshadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
1537         r_shadow_lightshadowmap_texturescale[2] = rsurface.rtlight->shadowmapatlasposition[0] + (noselfshadowpass ? size * 2 : 0);
1538         r_shadow_lightshadowmap_texturescale[3] = rsurface.rtlight->shadowmapatlasposition[1];
1539         r_shadow_lightshadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
1540         r_shadow_lightshadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
1541         r_shadow_lightshadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
1542         r_shadow_lightshadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
1543         if (r_shadow_shadowmap2ddepthbuffer)
1544         {
1545                 // completely different meaning than in depthtexture approach
1546                 r_shadow_lightshadowmap_parameters[1] = 0;
1547                 r_shadow_lightshadowmap_parameters[3] = -bias;
1548         }
1549 }
1550
1551 static void R_Shadow_RenderMode_ShadowMap(int side, int size, int x, int y)
1552 {
1553         float nearclip, farclip, bias;
1554         r_viewport_t viewport;
1555         int flipped;
1556
1557         if (r_shadow_rendermode != R_SHADOW_RENDERMODE_SHADOWMAP2D)
1558         {
1559                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
1560
1561                 R_Mesh_ResetTextureState();
1562                 R_Shadow_RenderMode_Reset();
1563                 if (r_shadow_shadowmap2ddepthbuffer)
1564                         R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
1565                 else
1566                         R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
1567                 R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
1568                 GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
1569                 GL_DepthMask(true);
1570                 GL_DepthTest(true);
1571         }
1572
1573         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
1574         farclip = 1.0f;
1575         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
1576
1577         R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL, x, y);
1578         R_SetViewport(&viewport);
1579         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
1580         flipped = (side & 1) ^ (side >> 2);
1581         r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
1582         r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
1583
1584         if (r_shadow_shadowmap2ddepthbuffer)
1585                 GL_ColorMask(1,1,1,1);
1586         else
1587                 GL_ColorMask(0,0,0,0);
1588         switch(vid.renderpath)
1589         {
1590         case RENDERPATH_GL32:
1591         case RENDERPATH_GLES2:
1592                 GL_CullFace(r_refdef.view.cullface_back);
1593                 break;
1594         }
1595
1596         // used in R_Q1BSP_DrawShadowMap code to check surfacesides[]
1597         r_shadow_shadowmapside = side;
1598 }
1599
1600 void R_Shadow_RenderMode_Lighting(qboolean transparent, qboolean shadowmapping, qboolean noselfshadowpass)
1601 {
1602         R_Mesh_ResetTextureState();
1603         if (transparent)
1604         {
1605                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
1606                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
1607                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
1608                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
1609         }
1610         if (shadowmapping)
1611                 R_Shadow_SetShadowmapParametersForLight(noselfshadowpass);
1612         R_Shadow_RenderMode_Reset();
1613         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1614         if (!transparent)
1615                 GL_DepthFunc(GL_EQUAL);
1616         // do global setup needed for the chosen lighting mode
1617         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
1618                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
1619         r_shadow_usingshadowmap2d = shadowmapping;
1620         r_shadow_rendermode = r_shadow_lightingrendermode;
1621 }
1622
1623 static const unsigned short bboxelements[36] =
1624 {
1625         5, 1, 3, 5, 3, 7,
1626         6, 2, 0, 6, 0, 4,
1627         7, 3, 2, 7, 2, 6,
1628         4, 0, 1, 4, 1, 5,
1629         4, 5, 7, 4, 7, 6,
1630         1, 0, 2, 1, 2, 3,
1631 };
1632
1633 static const float bboxpoints[8][3] =
1634 {
1635         {-1,-1,-1},
1636         { 1,-1,-1},
1637         {-1, 1,-1},
1638         { 1, 1,-1},
1639         {-1,-1, 1},
1640         { 1,-1, 1},
1641         {-1, 1, 1},
1642         { 1, 1, 1},
1643 };
1644
1645 void R_Shadow_RenderMode_DrawDeferredLight(qboolean shadowmapping)
1646 {
1647         int i;
1648         float vertex3f[8*3];
1649         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
1650 // do global setup needed for the chosen lighting mode
1651         R_Shadow_RenderMode_Reset();
1652         r_shadow_rendermode = r_shadow_lightingrendermode;
1653         R_EntityMatrix(&identitymatrix);
1654         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1655         if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0)
1656                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
1657         else
1658                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
1659
1660         r_shadow_usingshadowmap2d = shadowmapping;
1661
1662         // render the lighting
1663         R_SetupShader_DeferredLight(rsurface.rtlight);
1664         for (i = 0;i < 8;i++)
1665                 Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
1666         GL_ColorMask(1,1,1,1);
1667         GL_DepthMask(false);
1668         GL_DepthRange(0, 1);
1669         GL_PolygonOffset(0, 0);
1670         GL_DepthTest(true);
1671         GL_DepthFunc(GL_GREATER);
1672         GL_CullFace(r_refdef.view.cullface_back);
1673         R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0);
1674         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
1675 }
1676
1677 static qboolean R_Shadow_BounceGrid_CheckEnable(int flag)
1678 {
1679         qboolean enable = r_shadow_bouncegrid_state.capable && r_shadow_bouncegrid.integer != 0 && r_refdef.scene.worldmodel;
1680         int lightindex;
1681         int range;
1682         dlight_t *light;
1683         rtlight_t *rtlight;
1684         vec3_t lightcolor;
1685
1686         // see if there are really any lights to render...
1687         if (enable && r_shadow_bouncegrid_static.integer)
1688         {
1689                 enable = false;
1690                 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1691                 for (lightindex = 0;lightindex < range;lightindex++)
1692                 {
1693                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
1694                         if (!light || !(light->flags & flag))
1695                                 continue;
1696                         rtlight = &light->rtlight;
1697                         // when static, we skip styled lights because they tend to change...
1698                         if (rtlight->style > 0)
1699                                 continue;
1700                         VectorScale(rtlight->color, (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale), lightcolor);
1701                         if (!VectorLength2(lightcolor))
1702                                 continue;
1703                         enable = true;
1704                         break;
1705                 }
1706         }
1707
1708         return enable;
1709 }
1710
1711 static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t *settings)
1712 {
1713         qboolean s = r_shadow_bouncegrid_static.integer != 0;
1714         float spacing = bound(1.0f, s ? r_shadow_bouncegrid_static_spacing.value : r_shadow_bouncegrid_dynamic_spacing.value, 1024.0f);
1715         float quality = bound(0.0001f, (s ? r_shadow_bouncegrid_static_quality.value : r_shadow_bouncegrid_dynamic_quality.value), 1024.0f);
1716         float bounceminimumintensity = s ? r_shadow_bouncegrid_static_bounceminimumintensity.value : r_shadow_bouncegrid_dynamic_bounceminimumintensity.value;
1717
1718         // prevent any garbage in alignment padded areas as we'll be using memcmp
1719         memset(settings, 0, sizeof(*settings));
1720
1721         // build up a complete collection of the desired settings, so that memcmp can be used to compare parameters
1722         settings->staticmode                    = s;
1723         settings->blur                          = r_shadow_bouncegrid_blur.integer != 0;
1724         settings->floatcolors                   = bound(0, r_shadow_bouncegrid_floatcolors.integer, 2);
1725         settings->lightpathsize                 = bound(0.0f, r_shadow_bouncegrid_lightpathsize.value, 1024.0f);
1726         settings->directionalshading            = (s ? r_shadow_bouncegrid_static_directionalshading.integer != 0 : r_shadow_bouncegrid_dynamic_directionalshading.integer != 0) && r_shadow_bouncegrid_state.allowdirectionalshading;
1727         settings->dlightparticlemultiplier      = s ? 0 : r_shadow_bouncegrid_dynamic_dlightparticlemultiplier.value;
1728         settings->hitmodels                     = s ? false : r_shadow_bouncegrid_dynamic_hitmodels.integer != 0;
1729         settings->includedirectlighting         = r_shadow_bouncegrid_includedirectlighting.integer != 0 || r_shadow_bouncegrid.integer == 2;
1730         settings->lightradiusscale              = (s ? r_shadow_bouncegrid_static_lightradiusscale.value : r_shadow_bouncegrid_dynamic_lightradiusscale.value);
1731         settings->maxbounce                     = (s ? r_shadow_bouncegrid_static_maxbounce.integer : r_shadow_bouncegrid_dynamic_maxbounce.integer);
1732         settings->particlebounceintensity       = r_shadow_bouncegrid_particlebounceintensity.value;
1733         settings->particleintensity             = r_shadow_bouncegrid_particleintensity.value * (settings->directionalshading ? 4.0f : 1.0f) / 65536.0f;
1734         settings->maxphotons                    = s ? r_shadow_bouncegrid_static_maxphotons.integer : r_shadow_bouncegrid_dynamic_maxphotons.integer;
1735         settings->energyperphoton               = 4096.0f / quality;
1736         settings->spacing[0]                    = spacing;
1737         settings->spacing[1]                    = spacing;
1738         settings->spacing[2]                    = spacing;
1739         settings->rng_type                      = r_shadow_bouncegrid_rng_type.integer;
1740         settings->rng_seed                      = r_shadow_bouncegrid_rng_seed.integer;
1741         settings->bounceminimumintensity2       = bounceminimumintensity * bounceminimumintensity;
1742         settings->normalizevectors              = r_shadow_bouncegrid_normalizevectors.integer != 0;
1743         settings->subsamples                    = bound(1, r_shadow_bouncegrid_subsamples.integer, 4);
1744
1745         // bound the values for sanity
1746         settings->maxphotons = bound(1, settings->maxphotons, 25000000);
1747         settings->lightradiusscale = bound(0.0001f, settings->lightradiusscale, 1024.0f);
1748         settings->maxbounce = bound(0, settings->maxbounce, 16);
1749         settings->spacing[0] = bound(1, settings->spacing[0], 512);
1750         settings->spacing[1] = bound(1, settings->spacing[1], 512);
1751         settings->spacing[2] = bound(1, settings->spacing[2], 512);
1752 }
1753
1754 static void R_Shadow_BounceGrid_UpdateSpacing(void)
1755 {
1756         float m[16];
1757         int c[4];
1758         int resolution[3];
1759         int numpixels;
1760         vec3_t ispacing;
1761         vec3_t maxs;
1762         vec3_t mins;
1763         vec3_t size;
1764         vec3_t spacing;
1765         r_shadow_bouncegrid_settings_t *settings = &r_shadow_bouncegrid_state.settings;
1766
1767         // get the spacing values
1768         spacing[0] = settings->spacing[0];
1769         spacing[1] = settings->spacing[1];
1770         spacing[2] = settings->spacing[2];
1771         ispacing[0] = 1.0f / spacing[0];
1772         ispacing[1] = 1.0f / spacing[1];
1773         ispacing[2] = 1.0f / spacing[2];
1774
1775         // calculate texture size enclosing entire world bounds at the spacing
1776         if (r_refdef.scene.worldmodel)
1777         {
1778                 int lightindex;
1779                 int range;
1780                 qboolean bounds_set = false;
1781                 dlight_t *light;
1782                 rtlight_t *rtlight;
1783
1784                 // calculate bounds enclosing world lights as they should be noticably tighter 
1785                 // than the world bounds on maps with unlit monster containers (see e1m7 etc)
1786                 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1787                 for (lightindex = 0;lightindex < range;lightindex++)
1788                 {
1789                         const vec_t *rtlmins, *rtlmaxs;
1790
1791                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
1792                         if (!light)
1793                                 continue;
1794
1795                         rtlight = &light->rtlight;
1796                         rtlmins = rtlight->cullmins;
1797                         rtlmaxs = rtlight->cullmaxs;
1798
1799                         if (!bounds_set)
1800                         {
1801                                 VectorCopy(rtlmins, mins);
1802                                 VectorCopy(rtlmaxs, maxs);
1803                                 bounds_set = true;
1804                         }
1805                         else
1806                         {
1807                                 mins[0] = min(mins[0], rtlmins[0]);
1808                                 mins[1] = min(mins[1], rtlmins[1]);
1809                                 mins[2] = min(mins[2], rtlmins[2]);
1810                                 maxs[0] = max(maxs[0], rtlmaxs[0]);
1811                                 maxs[1] = max(maxs[1], rtlmaxs[1]);
1812                                 maxs[2] = max(maxs[2], rtlmaxs[2]);
1813                         }
1814                 }
1815
1816                 // limit to no larger than the world bounds
1817                 mins[0] = max(mins[0], r_refdef.scene.worldmodel->normalmins[0]);
1818                 mins[1] = max(mins[1], r_refdef.scene.worldmodel->normalmins[1]);
1819                 mins[2] = max(mins[2], r_refdef.scene.worldmodel->normalmins[2]);
1820                 maxs[0] = min(maxs[0], r_refdef.scene.worldmodel->normalmaxs[0]);
1821                 maxs[1] = min(maxs[1], r_refdef.scene.worldmodel->normalmaxs[1]);
1822                 maxs[2] = min(maxs[2], r_refdef.scene.worldmodel->normalmaxs[2]);
1823
1824                 VectorMA(mins, -2.0f, spacing, mins);
1825                 VectorMA(maxs, 2.0f, spacing, maxs);
1826         }
1827         else
1828         {
1829                 VectorSet(mins, -1048576.0f, -1048576.0f, -1048576.0f);
1830                 VectorSet(maxs,  1048576.0f,  1048576.0f,  1048576.0f);
1831         }
1832         VectorSubtract(maxs, mins, size);
1833         // now we can calculate the resolution we want
1834         c[0] = (int)floor(size[0] / spacing[0] + 0.5f);
1835         c[1] = (int)floor(size[1] / spacing[1] + 0.5f);
1836         c[2] = (int)floor(size[2] / spacing[2] + 0.5f);
1837         // figure out the exact texture size (honoring power of 2 if required)
1838         resolution[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
1839         resolution[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
1840         resolution[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
1841         size[0] = spacing[0] * resolution[0];
1842         size[1] = spacing[1] * resolution[1];
1843         size[2] = spacing[2] * resolution[2];
1844
1845         // if dynamic we may or may not want to use the world bounds
1846         // if the dynamic size is smaller than the world bounds, use it instead
1847         if (!settings->staticmode && (r_shadow_bouncegrid_dynamic_x.integer * r_shadow_bouncegrid_dynamic_y.integer * r_shadow_bouncegrid_dynamic_z.integer < resolution[0] * resolution[1] * resolution[2]))
1848         {
1849                 // we know the resolution we want
1850                 c[0] = r_shadow_bouncegrid_dynamic_x.integer;
1851                 c[1] = r_shadow_bouncegrid_dynamic_y.integer;
1852                 c[2] = r_shadow_bouncegrid_dynamic_z.integer;
1853                 // now we can calculate the texture size
1854                 resolution[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
1855                 resolution[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
1856                 resolution[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
1857                 size[0] = spacing[0] * resolution[0];
1858                 size[1] = spacing[1] * resolution[1];
1859                 size[2] = spacing[2] * resolution[2];
1860                 // center the rendering on the view
1861                 mins[0] = floor(r_refdef.view.origin[0] * ispacing[0] + 0.5f) * spacing[0] - 0.5f * size[0];
1862                 mins[1] = floor(r_refdef.view.origin[1] * ispacing[1] + 0.5f) * spacing[1] - 0.5f * size[1];
1863                 mins[2] = floor(r_refdef.view.origin[2] * ispacing[2] + 0.5f) * spacing[2] - 0.5f * size[2];
1864         }
1865
1866         // recalculate the maxs in case the resolution was not satisfactory
1867         VectorAdd(mins, size, maxs);
1868
1869         // check if this changed the texture size
1870         r_shadow_bouncegrid_state.createtexture = !(r_shadow_bouncegrid_state.texture && r_shadow_bouncegrid_state.resolution[0] == resolution[0] && r_shadow_bouncegrid_state.resolution[1] == resolution[1] && r_shadow_bouncegrid_state.resolution[2] == resolution[2] && r_shadow_bouncegrid_state.directional == r_shadow_bouncegrid_state.settings.directionalshading);
1871         r_shadow_bouncegrid_state.directional = r_shadow_bouncegrid_state.settings.directionalshading;
1872         VectorCopy(mins, r_shadow_bouncegrid_state.mins);
1873         VectorCopy(maxs, r_shadow_bouncegrid_state.maxs);
1874         VectorCopy(size, r_shadow_bouncegrid_state.size);
1875         VectorCopy(spacing, r_shadow_bouncegrid_state.spacing);
1876         VectorCopy(ispacing, r_shadow_bouncegrid_state.ispacing);
1877         VectorCopy(resolution, r_shadow_bouncegrid_state.resolution);
1878
1879         // reallocate pixels for this update if needed...
1880         r_shadow_bouncegrid_state.pixelbands = settings->directionalshading ? 8 : 1;
1881         r_shadow_bouncegrid_state.pixelsperband = resolution[0]*resolution[1]*resolution[2];
1882         r_shadow_bouncegrid_state.bytesperband = r_shadow_bouncegrid_state.pixelsperband*4;
1883         numpixels = r_shadow_bouncegrid_state.pixelsperband*r_shadow_bouncegrid_state.pixelbands;
1884         if (r_shadow_bouncegrid_state.numpixels != numpixels)
1885         {
1886                 if (r_shadow_bouncegrid_state.texture) { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
1887
1888                 r_shadow_bouncegrid_state.highpixels = NULL;
1889
1890                 if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
1891                 if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
1892                 if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
1893                 if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
1894                 if (r_shadow_bouncegrid_state.photons) { Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL; }
1895                 if (r_shadow_bouncegrid_state.photons_tasks) { Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL; }
1896                 if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
1897
1898                 r_shadow_bouncegrid_state.numpixels = numpixels;
1899         }
1900
1901         // update the bouncegrid matrix to put it in the world properly
1902         memset(m, 0, sizeof(m));
1903         m[0] = 1.0f / r_shadow_bouncegrid_state.size[0];
1904         m[3] = -r_shadow_bouncegrid_state.mins[0] * m[0];
1905         m[5] = 1.0f / r_shadow_bouncegrid_state.size[1];
1906         m[7] = -r_shadow_bouncegrid_state.mins[1] * m[5];
1907         m[10] = 1.0f / r_shadow_bouncegrid_state.size[2];
1908         m[11] = -r_shadow_bouncegrid_state.mins[2] * m[10];
1909         m[15] = 1.0f;
1910         Matrix4x4_FromArrayFloatD3D(&r_shadow_bouncegrid_state.matrix, m);
1911 }
1912
1913 static float R_Shadow_BounceGrid_RefractiveIndexAtPoint(vec3_t point)
1914 {
1915         // check material at shadoworigin to see what the initial refractive index should be
1916         int hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK;
1917         int skipsupercontentsmask = 0;
1918         int skipmaterialflagsmask = MATERIALFLAG_CUSTOMBLEND;
1919         trace_t trace = CL_TracePoint(point, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, true, false, NULL, true);
1920         if (trace.starttexture && (trace.starttexture->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER)))
1921                 return trace.starttexture->refractive_index;
1922         else if (trace.startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
1923                 return 1.333f; // water
1924         else
1925                 return 1.0003f; // air
1926 }
1927
1928 // enumerate world rtlights and sum the overall amount of light in the world,
1929 // from that we can calculate a scaling factor to fairly distribute photons
1930 // to all the lights
1931 //
1932 // this modifies rtlight->photoncolor and rtlight->photons
1933 static void R_Shadow_BounceGrid_AssignPhotons_Task(taskqueue_task_t *t)
1934 {
1935         // get the range of light numbers we'll be looping over:
1936         // range = static lights
1937         // range1 = dynamic lights (optional)
1938         // range2 = range + range1
1939         unsigned int range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1940         unsigned int range1 = r_shadow_bouncegrid_state.settings.staticmode ? 0 : r_refdef.scene.numlights;
1941         unsigned int range2 = range + range1;
1942         int flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
1943
1944         float normalphotonscaling;
1945         float photonscaling;
1946         float photonintensity;
1947         float photoncount = 0.0f;
1948         float lightintensity;
1949         float radius;
1950         float s;
1951         float w;
1952         vec3_t cullmins;
1953         vec3_t cullmaxs;
1954         unsigned int lightindex;
1955         dlight_t *light;
1956         rtlight_t *rtlight;
1957         int shootparticles;
1958         int shotparticles;
1959         float bounceminimumintensity2;
1960         float startrefractiveindex;
1961         unsigned int seed;
1962         randomseed_t randomseed;
1963         vec3_t baseshotcolor;
1964
1965         normalphotonscaling = 1.0f / max(0.0000001f, r_shadow_bouncegrid_state.settings.energyperphoton);
1966         for (lightindex = 0;lightindex < range2;lightindex++)
1967         {
1968                 if (lightindex < range)
1969                 {
1970                         light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
1971                         if (!light)
1972                                 continue;
1973                         rtlight = &light->rtlight;
1974                         VectorClear(rtlight->bouncegrid_photoncolor);
1975                         rtlight->bouncegrid_photons = 0;
1976                         rtlight->bouncegrid_hits = 0;
1977                         rtlight->bouncegrid_traces = 0;
1978                         rtlight->bouncegrid_effectiveradius = 0;
1979                         if (!(light->flags & flag))
1980                                 continue;
1981                         if (r_shadow_bouncegrid_state.settings.staticmode)
1982                         {
1983                                 // when static, we skip styled lights because they tend to change...
1984                                 if (rtlight->style > 0 && r_shadow_bouncegrid.integer != 2)
1985                                         continue;
1986                         }
1987                         else if (r_shadow_debuglight.integer >= 0 && (int)lightindex != r_shadow_debuglight.integer)
1988                                 continue;
1989                 }
1990                 else
1991                 {
1992                         rtlight = r_refdef.scene.lights[lightindex - range];
1993                         VectorClear(rtlight->bouncegrid_photoncolor);
1994                         rtlight->bouncegrid_photons = 0;
1995                         rtlight->bouncegrid_hits = 0;
1996                         rtlight->bouncegrid_traces = 0;
1997                         rtlight->bouncegrid_effectiveradius = 0;
1998                 }
1999                 // draw only visible lights (major speedup)
2000                 radius = rtlight->radius * r_shadow_bouncegrid_state.settings.lightradiusscale;
2001                 cullmins[0] = rtlight->shadoworigin[0] - radius;
2002                 cullmins[1] = rtlight->shadoworigin[1] - radius;
2003                 cullmins[2] = rtlight->shadoworigin[2] - radius;
2004                 cullmaxs[0] = rtlight->shadoworigin[0] + radius;
2005                 cullmaxs[1] = rtlight->shadoworigin[1] + radius;
2006                 cullmaxs[2] = rtlight->shadoworigin[2] + radius;
2007                 w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2008                 if (!r_shadow_bouncegrid_state.settings.staticmode)
2009                 {
2010                         // skip if the expanded light box does not touch any visible leafs
2011                         if (r_refdef.scene.worldmodel
2012                                 && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs
2013                                 && !r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, cullmins, cullmaxs))
2014                                 continue;
2015                         // skip if the expanded light box is not visible to traceline
2016                         // note that PrepareLight already did this check but for a smaller box, so we
2017                         // end up casting more traces per frame per light when using bouncegrid, which
2018                         // is probably fine (and they use the same timer)
2019                         if (r_shadow_culllights_trace.integer)
2020                         {
2021                                 if (rtlight->trace_timer != realtime && R_CanSeeBox(rtlight->trace_timer == 0 ? r_shadow_culllights_trace_tempsamples.integer : r_shadow_culllights_trace_samples.integer, r_shadow_culllights_trace_eyejitter.value, r_shadow_culllights_trace_enlarge.value, r_shadow_culllights_trace_expand.value, r_shadow_culllights_trace_pad.value, r_refdef.view.origin, rtlight->cullmins, rtlight->cullmaxs))
2022                                         rtlight->trace_timer = realtime;
2023                                 if (realtime - rtlight->trace_timer > r_shadow_culllights_trace_delay.value)
2024                                         continue;
2025                         }
2026                         // skip if expanded light box is offscreen
2027                         if (R_CullBox(cullmins, cullmaxs))
2028                                 continue;
2029                         // skip if overall light intensity is zero
2030                         if (w * VectorLength2(rtlight->color) == 0.0f)
2031                                 continue;
2032                 }
2033                 // a light that does not emit any light before style is applied, can be
2034                 // skipped entirely (it may just be a corona)
2035                 if (rtlight->radius == 0.0f || VectorLength2(rtlight->color) == 0.0f)
2036                         continue;
2037                 w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
2038                 VectorScale(rtlight->color, w, rtlight->bouncegrid_photoncolor);
2039                 // skip lights that will emit no photons
2040                 if (!VectorLength2(rtlight->bouncegrid_photoncolor))
2041                         continue;
2042                 // shoot particles from this light
2043                 // use a calculation for the number of particles that will not
2044                 // vary with lightstyle, otherwise we get randomized particle
2045                 // distribution, the seeded random is only consistent for a
2046                 // consistent number of particles on this light...
2047                 s = rtlight->radius;
2048                 lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2049                 if (lightindex >= range)
2050                         lightintensity *= r_shadow_bouncegrid_state.settings.dlightparticlemultiplier;
2051                 rtlight->bouncegrid_photons = lightintensity * s * s * normalphotonscaling;
2052                 photoncount += rtlight->bouncegrid_photons;
2053                 VectorScale(rtlight->bouncegrid_photoncolor, r_shadow_bouncegrid_state.settings.particleintensity * r_shadow_bouncegrid_state.settings.energyperphoton, rtlight->bouncegrid_photoncolor);
2054                 // if the lightstyle happens to be off right now, we can skip actually
2055                 // firing the photons, but we did have to count them in the total.
2056                 //if (VectorLength2(rtlight->photoncolor) == 0.0f)
2057                 //      rtlight->bouncegrid_photons = 0;
2058         }
2059         // the user provided an energyperphoton value which we try to use
2060         // if that results in too many photons to shoot this frame, then we cap it
2061         // which causes photons to appear/disappear from frame to frame, so we don't
2062         // like doing that in the typical case
2063         photonscaling = 1.0f;
2064         photonintensity = 1.0f;
2065         if (photoncount > r_shadow_bouncegrid_state.settings.maxphotons)
2066         {
2067                 photonscaling = r_shadow_bouncegrid_state.settings.maxphotons / photoncount;
2068                 photonintensity = 1.0f / photonscaling;
2069         }
2070
2071         // modify the lights to reflect our computed scaling
2072         for (lightindex = 0; lightindex < range2; lightindex++)
2073         {
2074                 if (lightindex < range)
2075                 {
2076                         light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2077                         if (!light)
2078                                 continue;
2079                         rtlight = &light->rtlight;
2080                 }
2081                 else
2082                         rtlight = r_refdef.scene.lights[lightindex - range];
2083                 rtlight->bouncegrid_photons *= photonscaling;
2084                 VectorScale(rtlight->bouncegrid_photoncolor, photonintensity, rtlight->bouncegrid_photoncolor);
2085         }
2086
2087         // compute a seed for the unstable random modes
2088         Math_RandomSeed_FromInts(&randomseed, 0, 0, 0, realtime * 1000.0);
2089         seed = realtime * 1000.0;
2090
2091         for (lightindex = 0; lightindex < range2; lightindex++)
2092         {
2093                 if (lightindex < range)
2094                 {
2095                         light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2096                         if (!light)
2097                                 continue;
2098                         rtlight = &light->rtlight;
2099                 }
2100                 else
2101                         rtlight = r_refdef.scene.lights[lightindex - range];
2102                 // note that this code used to keep track of residual photons and
2103                 // distribute them evenly to achieve exactly a desired photon count,
2104                 // but that caused unwanted flickering in dynamic mode
2105                 shootparticles = (int)floor(rtlight->bouncegrid_photons);
2106                 // skip if we won't be shooting any photons
2107                 if (!shootparticles)
2108                         continue;
2109                 radius = rtlight->radius * r_shadow_bouncegrid_state.settings.lightradiusscale;
2110                 //s = settings.particleintensity / shootparticles;
2111                 //VectorScale(rtlight->bouncegrid_photoncolor, s, baseshotcolor);
2112                 VectorCopy(rtlight->bouncegrid_photoncolor, baseshotcolor);
2113                 if (VectorLength2(baseshotcolor) <= 0.0f)
2114                         continue;
2115                 r_refdef.stats[r_stat_bouncegrid_lights]++;
2116                 r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
2117                 // we stop caring about bounces once the brightness goes below this fraction of the original intensity
2118                 bounceminimumintensity2 = VectorLength(baseshotcolor) * r_shadow_bouncegrid_state.settings.bounceminimumintensity2;
2119
2120                 // check material at shadoworigin to see what the initial refractive index should be
2121                 startrefractiveindex = R_Shadow_BounceGrid_RefractiveIndexAtPoint(rtlight->shadoworigin);
2122
2123                 // for seeded random we start the RNG with the position of the light
2124                 if (r_shadow_bouncegrid_state.settings.rng_seed >= 0)
2125                 {
2126                         union
2127                         {
2128                                 unsigned int i[4];
2129                                 float f[4];
2130                         }
2131                         u;
2132                         u.f[0] = rtlight->shadoworigin[0];
2133                         u.f[1] = rtlight->shadoworigin[1];
2134                         u.f[2] = rtlight->shadoworigin[2];
2135                         u.f[3] = 1;
2136                         switch (r_shadow_bouncegrid_state.settings.rng_type)
2137                         {
2138                         default:
2139                         case 0:
2140                                 // we have to shift the seed provided by the user because the result must be odd
2141                                 Math_RandomSeed_FromInts(&randomseed, u.i[0], u.i[1], u.i[2], u.i[3] ^ (r_shadow_bouncegrid_state.settings.rng_seed << 1));
2142                                 break;
2143                         case 1:
2144                                 seed = u.i[0] ^ u.i[1] ^ u.i[2] ^ u.i[3] ^ r_shadow_bouncegrid_state.settings.rng_seed;
2145                                 break;
2146                         }
2147                 }
2148
2149                 for (shotparticles = 0; shotparticles < shootparticles && r_shadow_bouncegrid_state.numphotons < r_shadow_bouncegrid_state.settings.maxphotons; shotparticles++)
2150                 {
2151                         r_shadow_bouncegrid_photon_t *p = r_shadow_bouncegrid_state.photons + r_shadow_bouncegrid_state.numphotons++;
2152                         VectorCopy(baseshotcolor, p->color);
2153                         VectorCopy(rtlight->shadoworigin, p->start);
2154                         switch (r_shadow_bouncegrid_state.settings.rng_type)
2155                         {
2156                         default:
2157                         case 0:
2158                                 // figure out a random direction for the initial photon to go
2159                                 VectorLehmerRandom(&randomseed, p->end);
2160                                 break;
2161                         case 1:
2162                                 // figure out a random direction for the initial photon to go
2163                                 VectorCheeseRandom(seed, p->end);
2164                                 break;
2165                         }
2166
2167                         // we want a uniform distribution spherically, not merely within the sphere
2168                         if (r_shadow_bouncegrid_state.settings.normalizevectors)
2169                                 VectorNormalize(p->end);
2170
2171                         VectorMA(p->start, radius, p->end, p->end);
2172                         p->bounceminimumintensity2 = bounceminimumintensity2;
2173                         p->startrefractiveindex = startrefractiveindex;
2174                         p->numpaths = 0;
2175                 }
2176         }
2177
2178         t->done = 1;
2179 }
2180
2181 static void R_Shadow_BounceGrid_Slice(int zi)
2182 {
2183         float *highpixels = r_shadow_bouncegrid_state.highpixels;
2184         int xi, yi; // pixel increments
2185         float color[32] = { 0 };
2186         float radius = r_shadow_bouncegrid_state.settings.lightpathsize;
2187         float iradius = 1.0f / radius;
2188         int slicemins[3], slicemaxs[3];
2189         int resolution[3];
2190         int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
2191         int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2192         int photonindex;
2193         int samples = r_shadow_bouncegrid_state.settings.subsamples;
2194         float isamples = 1.0f / samples;
2195         float samplescolorscale = isamples * isamples * isamples;
2196
2197         // we use these a lot, so get a local copy
2198         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
2199
2200         for (photonindex = 0; photonindex < r_shadow_bouncegrid_state.numphotons; photonindex++)
2201         {
2202                 r_shadow_bouncegrid_photon_t *photon = r_shadow_bouncegrid_state.photons + photonindex;
2203                 int pathindex;
2204                 for (pathindex = 0; pathindex < photon->numpaths; pathindex++)
2205                 {
2206                         r_shadow_bouncegrid_photon_path_t *path = photon->paths + pathindex;
2207                         float pathstart[3], pathend[3], pathmins[3], pathmaxs[3], pathdelta[3], pathdir[3], pathlength2, pathilength;
2208
2209                         VectorSubtract(path->start, r_shadow_bouncegrid_state.mins, pathstart);
2210                         VectorSubtract(path->end, r_shadow_bouncegrid_state.mins, pathend);
2211
2212                         pathmins[2] = min(pathstart[2], pathend[2]);
2213                         slicemins[2] = (int)floor((pathmins[2] - radius) * r_shadow_bouncegrid_state.ispacing[2]);
2214                         pathmaxs[2] = max(pathstart[2], pathend[2]);
2215                         slicemaxs[2] = (int)floor((pathmaxs[2] + radius) * r_shadow_bouncegrid_state.ispacing[2] + 1);
2216
2217                         // skip if the path doesn't touch this slice
2218                         if (zi < slicemins[2] || zi >= slicemaxs[2])
2219                                 continue;
2220
2221                         pathmins[0] = min(pathstart[0], pathend[0]);
2222                         slicemins[0] = (int)floor((pathmins[0] - radius) * r_shadow_bouncegrid_state.ispacing[0]);
2223                         slicemins[0] = max(slicemins[0], 1);
2224                         pathmaxs[0] = max(pathstart[0], pathend[0]);
2225                         slicemaxs[0] = (int)floor((pathmaxs[0] + radius) * r_shadow_bouncegrid_state.ispacing[0]);
2226                         slicemaxs[0] = min(slicemaxs[0], resolution[0] - 1);
2227
2228                         pathmins[1] = min(pathstart[1], pathend[1]);
2229                         slicemins[1] = (int)floor((pathmins[1] - radius) * r_shadow_bouncegrid_state.ispacing[1] + 1);
2230                         slicemins[1] = max(slicemins[1], 1);
2231                         pathmaxs[1] = max(pathstart[1], pathend[1]);
2232                         slicemaxs[1] = (int)floor((pathmaxs[1] + radius) * r_shadow_bouncegrid_state.ispacing[1] + 1);
2233                         slicemaxs[1] = min(slicemaxs[1], resolution[1] - 1);
2234
2235                         // skip if the path is out of bounds on X or Y
2236                         if (slicemins[0] >= slicemaxs[0] || slicemins[1] >= slicemaxs[1])
2237                                 continue;
2238
2239                         // calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
2240                         // accumulate average shotcolor
2241                         VectorSubtract(pathend, pathstart, pathdelta);
2242                         pathlength2 = VectorLength2(pathdelta);
2243                         pathilength = pathlength2 > 0.0f ? 1.0f / sqrt(pathlength2) : 0.0f;
2244                         VectorScale(pathdelta, pathilength, pathdir);
2245                         // the color is scaled by the number of subsamples
2246                         color[0] = path->color[0] * samplescolorscale;
2247                         color[1] = path->color[1] * samplescolorscale;
2248                         color[2] = path->color[2] * samplescolorscale;
2249                         color[3] = 0.0f;
2250                         if (pixelbands > 1)
2251                         {
2252                                 // store bentnormal in case the shader has a use for it,
2253                                 // bentnormal is an intensity-weighted average of the directions,
2254                                 // and will be normalized on conversion to texture pixels.
2255                                 float intensity = VectorLength(color);
2256                                 color[4] = pathdir[0] * intensity;
2257                                 color[5] = pathdir[1] * intensity;
2258                                 color[6] = pathdir[2] * intensity;
2259                                 color[7] = intensity;
2260                                 // for each color component (R, G, B) calculate the amount that a
2261                                 // direction contributes
2262                                 color[8] = color[0] * max(0.0f, pathdir[0]);
2263                                 color[9] = color[0] * max(0.0f, pathdir[1]);
2264                                 color[10] = color[0] * max(0.0f, pathdir[2]);
2265                                 color[11] = 0.0f;
2266                                 color[12] = color[1] * max(0.0f, pathdir[0]);
2267                                 color[13] = color[1] * max(0.0f, pathdir[1]);
2268                                 color[14] = color[1] * max(0.0f, pathdir[2]);
2269                                 color[15] = 0.0f;
2270                                 color[16] = color[2] * max(0.0f, pathdir[0]);
2271                                 color[17] = color[2] * max(0.0f, pathdir[1]);
2272                                 color[18] = color[2] * max(0.0f, pathdir[2]);
2273                                 color[19] = 0.0f;
2274                                 // and do the same for negative directions
2275                                 color[20] = color[0] * max(0.0f, -pathdir[0]);
2276                                 color[21] = color[0] * max(0.0f, -pathdir[1]);
2277                                 color[22] = color[0] * max(0.0f, -pathdir[2]);
2278                                 color[23] = 0.0f;
2279                                 color[24] = color[1] * max(0.0f, -pathdir[0]);
2280                                 color[25] = color[1] * max(0.0f, -pathdir[1]);
2281                                 color[26] = color[1] * max(0.0f, -pathdir[2]);
2282                                 color[27] = 0.0f;
2283                                 color[28] = color[2] * max(0.0f, -pathdir[0]);
2284                                 color[29] = color[2] * max(0.0f, -pathdir[1]);
2285                                 color[30] = color[2] * max(0.0f, -pathdir[2]);
2286                                 color[31] = 0.0f;
2287                         }
2288
2289                         for (yi = slicemins[1]; yi < slicemaxs[1]; yi++)
2290                         {
2291                                 for (xi = slicemins[0]; xi < slicemaxs[0]; xi++)
2292                                 {
2293                                         float sample[3], diff[3], nearest[3], along, distance2;
2294                                         float *p = highpixels + 4 * ((zi * resolution[1] + yi) * resolution[0] + xi);
2295                                         int xs, ys, zs;
2296                                         // loop over the subsamples
2297                                         for (zs = 0; zs < samples; zs++)
2298                                         {
2299                                                 sample[2] = (zi + (zs + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[2];
2300                                                 for (ys = 0; ys < samples; ys++)
2301                                                 {
2302                                                         sample[1] = (yi + (ys + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[1];
2303                                                         for (xs = 0; xs < samples; xs++)
2304                                                         {
2305                                                                 sample[0] = (xi + (xs + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[0];
2306
2307                                                                 // measure distance from subsample to line segment and see if it is within radius
2308                                                                 along = DotProduct(sample, pathdir) * pathilength;
2309                                                                 if (along <= 0)
2310                                                                         VectorCopy(pathstart, nearest);
2311                                                                 else if (along >= 1)
2312                                                                         VectorCopy(pathend, nearest);
2313                                                                 else
2314                                                                         VectorLerp(pathstart, along, pathend, nearest);
2315                                                                 VectorSubtract(sample, nearest, diff);
2316                                                                 VectorScale(diff, iradius, diff);
2317                                                                 distance2 = VectorLength2(diff);
2318                                                                 if (distance2 < 1.0f)
2319                                                                 {
2320                                                                         // contribute some color to this pixel, across all bands
2321                                                                         float w = 1.0f - sqrt(distance2);
2322                                                                         int band;
2323                                                                         w *= w;
2324                                                                         if (pixelbands > 1)
2325                                                                         {
2326                                                                                 // small optimization for alpha - only color[7] is non-zero, so skip the rest of the alpha elements.
2327                                                                                 p[pixelsperband * 4 + 3] += color[7] * w;
2328                                                                         }
2329                                                                         for (band = 0; band < pixelbands; band++)
2330                                                                         {
2331                                                                                 // add to the pixel color (RGB only - see above)
2332                                                                                 p[band * pixelsperband * 4 + 0] += color[band * 4 + 0] * w;
2333                                                                                 p[band * pixelsperband * 4 + 1] += color[band * 4 + 1] * w;
2334                                                                                 p[band * pixelsperband * 4 + 2] += color[band * 4 + 2] * w;
2335                                                                         }
2336                                                                 }
2337                                                         }
2338                                                 }
2339                                         }
2340                                 }
2341                         }
2342                 }
2343         }
2344 }
2345
2346 static void R_Shadow_BounceGrid_Slice_Task(taskqueue_task_t *t)
2347 {
2348         R_Shadow_BounceGrid_Slice((int)t->i[0]);
2349         t->done = 1;
2350 }
2351
2352 static void R_Shadow_BounceGrid_EnqueueSlices_Task(taskqueue_task_t *t)
2353 {
2354         int i, slices;
2355         // we need to wait for the texture clear to finish before we start adding light to it
2356         if (r_shadow_bouncegrid_state.cleartex_task.done == 0)
2357         {
2358                 TaskQueue_Yield(t);
2359                 return;
2360         }
2361         slices = r_shadow_bouncegrid_state.resolution[2] - 2;
2362         for (i = 0; i < slices; i++)
2363                 TaskQueue_Setup(r_shadow_bouncegrid_state.slices_tasks + i, NULL, R_Shadow_BounceGrid_Slice_Task, i + 1, 0, NULL, NULL);
2364         TaskQueue_Enqueue(slices, r_shadow_bouncegrid_state.slices_tasks);
2365         TaskQueue_Setup(&r_shadow_bouncegrid_state.slices_done_task, NULL, TaskQueue_Task_CheckTasksDone, slices, 0, r_shadow_bouncegrid_state.slices_tasks, 0);
2366         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.slices_done_task);
2367         t->done = 1;
2368 }
2369
2370 static void R_Shadow_BounceGrid_BlurPixelsInDirection(const float *inpixels, float *outpixels, int off)
2371 {
2372         const float *inpixel;
2373         float *outpixel;
2374         int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2375         int pixelband;
2376         unsigned int index;
2377         unsigned int x, y, z;
2378         unsigned int resolution[3];
2379         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
2380         for (pixelband = 0;pixelband < pixelbands;pixelband++)
2381         {
2382                 for (z = 1;z < resolution[2]-1;z++)
2383                 {
2384                         for (y = 1;y < resolution[1]-1;y++)
2385                         {
2386                                 x = 1;
2387                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2388                                 inpixel = inpixels + 4*index;
2389                                 outpixel = outpixels + 4*index;
2390                                 for (;x < resolution[0]-1;x++, inpixel += 4, outpixel += 4)
2391                                 {
2392                                         outpixel[0] = (inpixel[0] + inpixel[  off] + inpixel[0-off]) * (1.0f / 3.0);
2393                                         outpixel[1] = (inpixel[1] + inpixel[1+off] + inpixel[1-off]) * (1.0f / 3.0);
2394                                         outpixel[2] = (inpixel[2] + inpixel[2+off] + inpixel[2-off]) * (1.0f / 3.0);
2395                                         outpixel[3] = (inpixel[3] + inpixel[3+off] + inpixel[3-off]) * (1.0f / 3.0);
2396                                 }
2397                         }
2398                 }
2399         }
2400 }
2401
2402 static void R_Shadow_BounceGrid_BlurPixels_Task(taskqueue_task_t *t)
2403 {
2404         float *pixels[4];
2405         unsigned int resolution[3];
2406         if (r_shadow_bouncegrid_state.settings.blur)
2407         {
2408                 VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
2409
2410                 pixels[0] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
2411                 pixels[1] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1];
2412                 pixels[2] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
2413                 pixels[3] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1];
2414
2415                 // blur on X
2416                 R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[0], pixels[1], 4);
2417                 // blur on Y
2418                 R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[1], pixels[2], resolution[0] * 4);
2419                 // blur on Z
2420                 R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[2], pixels[3], resolution[0] * resolution[1] * 4);
2421
2422                 // toggle the state, highpixels now points to pixels[3] result
2423                 r_shadow_bouncegrid_state.highpixels_index ^= 1;
2424                 r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
2425         }
2426         t->done = 1;
2427 }
2428
2429 static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
2430 {
2431         int floatcolors = r_shadow_bouncegrid_state.settings.floatcolors;
2432         unsigned char *pixelsbgra8 = NULL;
2433         unsigned char *pixelbgra8;
2434         unsigned short *pixelsrgba16f = NULL;
2435         unsigned short *pixelrgba16f;
2436         float *pixelsrgba32f = NULL;
2437         float *highpixels = r_shadow_bouncegrid_state.highpixels;
2438         float *highpixel;
2439         float *bandpixel;
2440         unsigned int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
2441         unsigned int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2442         unsigned int pixelband;
2443         unsigned int x, y, z;
2444         unsigned int index, bandindex;
2445         unsigned int resolution[3];
2446         int c[4];
2447         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
2448
2449         if (r_shadow_bouncegrid_state.createtexture && r_shadow_bouncegrid_state.texture)
2450         {
2451                 R_FreeTexture(r_shadow_bouncegrid_state.texture);
2452                 r_shadow_bouncegrid_state.texture = NULL;
2453         }
2454
2455         // if bentnormals exist, we need to normalize and bias them for the shader
2456         if (pixelbands > 1)
2457         {
2458                 pixelband = 1;
2459                 for (z = 0;z < resolution[2]-1;z++)
2460                 {
2461                         for (y = 0;y < resolution[1]-1;y++)
2462                         {
2463                                 x = 1;
2464                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2465                                 highpixel = highpixels + 4*index;
2466                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2467                                 {
2468                                         // only convert pixels that were hit by photons
2469                                         if (highpixel[3] != 0.0f)
2470                                                 VectorNormalize(highpixel);
2471                                         VectorSet(highpixel, highpixel[0] * 0.5f + 0.5f, highpixel[1] * 0.5f + 0.5f, highpixel[2] * 0.5f + 0.5f);
2472                                         highpixel[pixelsperband * 4 + 3] = 1.0f;
2473                                 }
2474                         }
2475                 }
2476         }
2477
2478         // start by clearing the pixels array - we won't be writing to all of it
2479         //
2480         // then process only the pixels that have at least some color, skipping
2481         // the higher bands for speed on pixels that are black
2482         switch (floatcolors)
2483         {
2484         case 0:
2485                 if (r_shadow_bouncegrid_state.u8pixels == NULL)
2486                         r_shadow_bouncegrid_state.u8pixels = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned char[4]));
2487                 pixelsbgra8 = r_shadow_bouncegrid_state.u8pixels;
2488                 for (pixelband = 0;pixelband < pixelbands;pixelband++)
2489                 {
2490                         if (pixelband == 1)
2491                                 memset(pixelsbgra8 + pixelband * r_shadow_bouncegrid_state.bytesperband, 128, r_shadow_bouncegrid_state.bytesperband);
2492                         else
2493                                 memset(pixelsbgra8 + pixelband * r_shadow_bouncegrid_state.bytesperband, 0, r_shadow_bouncegrid_state.bytesperband);
2494                 }
2495                 for (z = 1;z < resolution[2]-1;z++)
2496                 {
2497                         for (y = 1;y < resolution[1]-1;y++)
2498                         {
2499                                 x = 1;
2500                                 pixelband = 0;
2501                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2502                                 highpixel = highpixels + 4*index;
2503                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2504                                 {
2505                                         // only convert pixels that were hit by photons
2506                                         if (VectorLength2(highpixel))
2507                                         {
2508                                                 // normalize the bentnormal now
2509                                                 if (pixelbands > 1)
2510                                                 {
2511                                                         VectorNormalize(highpixel + pixelsperband * 4);
2512                                                         highpixel[pixelsperband * 4 + 3] = 1.0f;
2513                                                 }
2514                                                 // process all of the pixelbands for this pixel
2515                                                 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
2516                                                 {
2517                                                         pixelbgra8 = pixelsbgra8 + 4*bandindex;
2518                                                         bandpixel = highpixels + 4*bandindex;
2519                                                         c[0] = (int)(bandpixel[0]*256.0f);
2520                                                         c[1] = (int)(bandpixel[1]*256.0f);
2521                                                         c[2] = (int)(bandpixel[2]*256.0f);
2522                                                         c[3] = (int)(bandpixel[3]*256.0f);
2523                                                         pixelbgra8[2] = (unsigned char)bound(0, c[0], 255);
2524                                                         pixelbgra8[1] = (unsigned char)bound(0, c[1], 255);
2525                                                         pixelbgra8[0] = (unsigned char)bound(0, c[2], 255);
2526                                                         pixelbgra8[3] = (unsigned char)bound(0, c[3], 255);
2527                                                 }
2528                                         }
2529                                 }
2530                         }
2531                 }
2532
2533                 if (!r_shadow_bouncegrid_state.createtexture)
2534                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixelsbgra8, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
2535                 else
2536                         r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, pixelsbgra8, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2537                 break;
2538         case 1:
2539                 if (r_shadow_bouncegrid_state.fp16pixels == NULL)
2540                         r_shadow_bouncegrid_state.fp16pixels = (unsigned short *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
2541                 pixelsrgba16f = r_shadow_bouncegrid_state.fp16pixels;
2542                 memset(pixelsrgba16f, 0, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
2543                 for (z = 1;z < resolution[2]-1;z++)
2544                 {
2545                         for (y = 1;y < resolution[1]-1;y++)
2546                         {
2547                                 x = 1;
2548                                 pixelband = 0;
2549                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2550                                 highpixel = highpixels + 4*index;
2551                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2552                                 {
2553                                         // only convert pixels that were hit by photons
2554                                         if (VectorLength2(highpixel))
2555                                         {
2556                                                 // process all of the pixelbands for this pixel
2557                                                 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
2558                                                 {
2559                                                         // time to have fun with IEEE 754 bit hacking...
2560                                                         union {
2561                                                                 float f[4];
2562                                                                 unsigned int raw[4];
2563                                                         } u;
2564                                                         pixelrgba16f = pixelsrgba16f + 4*bandindex;
2565                                                         bandpixel = highpixels + 4*bandindex;
2566                                                         VectorCopy4(bandpixel, u.f);
2567                                                         VectorCopy4(u.raw, c);
2568                                                         // this math supports negative numbers, snaps denormals to zero
2569                                                         //pixelrgba16f[0] = (unsigned short)(((c[0] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[0] - 0x38000000) >> 13) & 0x7FFF) | ((c[0] >> 16) & 0x8000));
2570                                                         //pixelrgba16f[1] = (unsigned short)(((c[1] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[1] - 0x38000000) >> 13) & 0x7FFF) | ((c[1] >> 16) & 0x8000));
2571                                                         //pixelrgba16f[2] = (unsigned short)(((c[2] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[2] - 0x38000000) >> 13) & 0x7FFF) | ((c[2] >> 16) & 0x8000));
2572                                                         //pixelrgba16f[3] = (unsigned short)(((c[3] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[3] - 0x38000000) >> 13) & 0x7FFF) | ((c[3] >> 16) & 0x8000));
2573                                                         // this math does not support negative
2574                                                         pixelrgba16f[0] = (unsigned short)((c[0] < 0x38000000) ? 0 : ((c[0] - 0x38000000) >> 13));
2575                                                         pixelrgba16f[1] = (unsigned short)((c[1] < 0x38000000) ? 0 : ((c[1] - 0x38000000) >> 13));
2576                                                         pixelrgba16f[2] = (unsigned short)((c[2] < 0x38000000) ? 0 : ((c[2] - 0x38000000) >> 13));
2577                                                         pixelrgba16f[3] = (unsigned short)((c[3] < 0x38000000) ? 0 : ((c[3] - 0x38000000) >> 13));
2578                                                 }
2579                                         }
2580                                 }
2581                         }
2582                 }
2583
2584                 if (!r_shadow_bouncegrid_state.createtexture)
2585                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba16f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
2586                 else
2587                         r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba16f, TEXTYPE_COLORBUFFER16F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2588                 break;
2589         case 2:
2590                 // our native format happens to match, so this is easy.
2591                 pixelsrgba32f = highpixels;
2592
2593                 if (!r_shadow_bouncegrid_state.createtexture)
2594                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba32f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
2595                 else
2596                         r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba32f, TEXTYPE_COLORBUFFER32F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2597                 break;
2598         }
2599
2600         r_shadow_bouncegrid_state.lastupdatetime = realtime;
2601 }
2602
2603 void R_Shadow_BounceGrid_ClearTex_Task(taskqueue_task_t *t)
2604 {
2605         memset(r_shadow_bouncegrid_state.highpixels, 0, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2606         t->done = 1;
2607 }
2608
2609 static void R_Shadow_BounceGrid_TracePhotons_Shot(r_shadow_bouncegrid_photon_t *p, int remainingbounces, vec3_t shotstart, vec3_t shotend, vec3_t shotcolor, float bounceminimumintensity2, float previousrefractiveindex)
2610 {
2611         int hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask;
2612         vec3_t shothit;
2613         vec3_t surfacenormal;
2614         vec3_t reflectstart, reflectend, reflectcolor;
2615         vec3_t refractstart, refractend, refractcolor;
2616         vec_t s;
2617         float reflectamount = 1.0f;
2618         trace_t cliptrace;
2619         // figure out what we want to interact with
2620         hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK;
2621         skipsupercontentsmask = 0;
2622         skipmaterialflagsmask = MATERIALFLAG_CUSTOMBLEND;
2623         //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
2624         //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
2625         if (r_shadow_bouncegrid_state.settings.staticmode || r_shadow_bouncegrid_state.settings.rng_seed < 0 || r_shadow_bouncegrid_threaded.integer)
2626         {
2627                 // static mode fires a LOT of rays but none of them are identical, so they are not cached
2628                 // non-stable random in dynamic mode also never reuses a direction, so there's no reason to cache it
2629                 cliptrace = CL_TraceLine(shotstart, shotend, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, collision_extendmovelength.value, true, false, NULL, true, true);
2630         }
2631         else
2632         {
2633                 // dynamic mode fires many rays and most will match the cache from the previous frame
2634                 cliptrace = CL_Cache_TraceLineSurfaces(shotstart, shotend, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
2635         }
2636         VectorCopy(cliptrace.endpos, shothit);
2637         if ((remainingbounces == r_shadow_bouncegrid_state.settings.maxbounce || r_shadow_bouncegrid_state.settings.includedirectlighting) && p->numpaths < PHOTON_MAX_PATHS)
2638         {
2639                 qboolean notculled = true;
2640                 // cull paths that fail R_CullBox in dynamic mode
2641                 if (!r_shadow_bouncegrid_state.settings.staticmode
2642                         && r_shadow_bouncegrid_dynamic_culllightpaths.integer)
2643                 {
2644                         vec3_t cullmins, cullmaxs;
2645                         cullmins[0] = min(shotstart[0], shothit[0]) - r_shadow_bouncegrid_state.settings.spacing[0] - r_shadow_bouncegrid_state.settings.lightpathsize;
2646                         cullmins[1] = min(shotstart[1], shothit[1]) - r_shadow_bouncegrid_state.settings.spacing[1] - r_shadow_bouncegrid_state.settings.lightpathsize;
2647                         cullmins[2] = min(shotstart[2], shothit[2]) - r_shadow_bouncegrid_state.settings.spacing[2] - r_shadow_bouncegrid_state.settings.lightpathsize;
2648                         cullmaxs[0] = max(shotstart[0], shothit[0]) + r_shadow_bouncegrid_state.settings.spacing[0] + r_shadow_bouncegrid_state.settings.lightpathsize;
2649                         cullmaxs[1] = max(shotstart[1], shothit[1]) + r_shadow_bouncegrid_state.settings.spacing[1] + r_shadow_bouncegrid_state.settings.lightpathsize;
2650                         cullmaxs[2] = max(shotstart[2], shothit[2]) + r_shadow_bouncegrid_state.settings.spacing[2] + r_shadow_bouncegrid_state.settings.lightpathsize;
2651                         if (R_CullBox(cullmins, cullmaxs))
2652                                 notculled = false;
2653                 }
2654                 if (notculled)
2655                 {
2656                         r_shadow_bouncegrid_photon_path_t *path = p->paths + p->numpaths++;
2657                         VectorCopy(shotstart, path->start);
2658                         VectorCopy(shothit, path->end);
2659                         VectorCopy(shotcolor, path->color);
2660                 }
2661         }
2662         if (cliptrace.fraction < 1.0f && remainingbounces > 0)
2663         {
2664                 // scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
2665                 // also clamp the resulting color to never add energy, even if the user requests extreme values
2666                 VectorCopy(cliptrace.plane.normal, surfacenormal);
2667                 VectorSet(reflectcolor, 0.5f, 0.5f, 0.5f);
2668                 VectorClear(refractcolor);
2669                 // FIXME: we need to determine the exact triangle, vertex color and texcoords and texture color and texture normal for the impacted point
2670                 if (cliptrace.hittexture)
2671                 {
2672                         if (cliptrace.hittexture->currentskinframe)
2673                                 VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, reflectcolor);
2674                         if (cliptrace.hittexture->currentalpha < 1.0f && (cliptrace.hittexture->currentmaterialflags & (MATERIALFLAG_ALPHA | MATERIALFLAG_ALPHATEST)))
2675                         {
2676                                 reflectamount *= cliptrace.hittexture->currentalpha;
2677                                 if (cliptrace.hittexture->currentskinframe)
2678                                         reflectamount *= cliptrace.hittexture->currentskinframe->avgcolor[3];
2679                         }
2680                         if (cliptrace.hittexture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2681                         {
2682                                 float Fresnel;
2683                                 vec3_t lightdir;
2684                                 //reflectchance = pow(min(1.0f, 1.0f - cliptrace.
2685                                 VectorSubtract(shotstart, shotend, lightdir);
2686                                 VectorNormalize(lightdir);
2687                                 Fresnel = min(1.0f, 1.0f - DotProduct(lightdir, surfacenormal));
2688                                 Fresnel = Fresnel * Fresnel * (cliptrace.hittexture->reflectmax - cliptrace.hittexture->reflectmin) + cliptrace.hittexture->reflectmin;
2689                                 reflectamount *= Fresnel;
2690                                 VectorCopy(cliptrace.hittexture->refractcolor4f, refractcolor);
2691                         }
2692                         if (cliptrace.hittexture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2693                                 VectorCopy(cliptrace.hittexture->refractcolor4f, refractcolor);
2694                         // make sure we do not gain energy even if surface colors are out of bounds
2695                         reflectcolor[0] = min(reflectcolor[0], 1.0f);
2696                         reflectcolor[1] = min(reflectcolor[1], 1.0f);
2697                         reflectcolor[2] = min(reflectcolor[2], 1.0f);
2698                         refractcolor[0] = min(refractcolor[0], 1.0f);
2699                         refractcolor[1] = min(refractcolor[1], 1.0f);
2700                         refractcolor[2] = min(refractcolor[2], 1.0f);
2701                 }
2702                 // reflected and refracted shots
2703                 VectorScale(reflectcolor, r_shadow_bouncegrid_state.settings.particlebounceintensity * reflectamount, reflectcolor);
2704                 VectorScale(refractcolor, (1.0f - reflectamount), refractcolor);
2705                 VectorMultiply(reflectcolor, shotcolor, reflectcolor);
2706                 VectorMultiply(refractcolor, shotcolor, refractcolor);
2707
2708                 if (VectorLength2(reflectcolor) >= bounceminimumintensity2)
2709                 {
2710                         // reflect the remaining portion of the line across plane normal
2711                         VectorSubtract(shotend, shothit, reflectend);
2712                         VectorReflect(reflectend, 1.0, surfacenormal, reflectend);
2713                         // calculate the new line start and end
2714                         VectorCopy(shothit, reflectstart);
2715                         VectorAdd(reflectstart, reflectend, reflectend);
2716                         R_Shadow_BounceGrid_TracePhotons_Shot(p, remainingbounces - 1, reflectstart, reflectend, reflectcolor, bounceminimumintensity2, previousrefractiveindex);
2717                 }
2718
2719                 if (VectorLength2(refractcolor) >= bounceminimumintensity2)
2720                 {
2721                         // Check what refractive index is on the other side
2722                         float refractiveindex;
2723                         VectorMA(shothit, 0.0625f, cliptrace.plane.normal, refractstart);
2724                         refractiveindex = R_Shadow_BounceGrid_RefractiveIndexAtPoint(refractstart);
2725                         // reflect the remaining portion of the line across plane normal
2726                         VectorSubtract(shotend, shothit, refractend);
2727                         s = refractiveindex / previousrefractiveindex;
2728                         VectorReflect(refractend, -1.0f / s, surfacenormal, refractend);
2729                         // we also need to reflect the start to the other side of the plane so it doesn't just hit the same surface again
2730                         // calculate the new line start and end
2731                         VectorMA(shothit, 0.0625f, cliptrace.plane.normal, refractstart);
2732                         VectorAdd(refractstart, refractend, refractend);
2733                         R_Shadow_BounceGrid_TracePhotons_Shot(p, remainingbounces - 1, refractstart, refractend, refractcolor, bounceminimumintensity2, refractiveindex);
2734                 }
2735         }
2736 }
2737
2738 static void R_Shadow_BounceGrid_TracePhotons_ShotTask(taskqueue_task_t *t)
2739 {
2740         r_shadow_bouncegrid_photon_t *p = (r_shadow_bouncegrid_photon_t *)t->p[0];
2741         R_Shadow_BounceGrid_TracePhotons_Shot(p, r_shadow_bouncegrid_state.settings.maxbounce, p->start, p->end, p->color, p->bounceminimumintensity2, p->startrefractiveindex);
2742         t->done = 1;
2743 }
2744
2745 static void R_Shadow_BounceGrid_EnqueuePhotons_Task(taskqueue_task_t *t)
2746 {
2747         int i;
2748         for (i = 0; i < r_shadow_bouncegrid_state.numphotons; i++)
2749                 TaskQueue_Setup(r_shadow_bouncegrid_state.photons_tasks + i, NULL, R_Shadow_BounceGrid_TracePhotons_ShotTask, 0, 0, r_shadow_bouncegrid_state.photons + i, NULL);
2750         TaskQueue_Setup(&r_shadow_bouncegrid_state.photons_done_task, NULL, TaskQueue_Task_CheckTasksDone, r_shadow_bouncegrid_state.numphotons, 0, r_shadow_bouncegrid_state.photons_tasks, NULL);
2751         if (r_shadow_bouncegrid_threaded.integer)
2752         {
2753                 TaskQueue_Enqueue(r_shadow_bouncegrid_state.numphotons, r_shadow_bouncegrid_state.photons_tasks);
2754                 TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.photons_done_task);
2755         }
2756         else
2757         {
2758                 // when not threaded we still have to report task status
2759                 for (i = 0; i < r_shadow_bouncegrid_state.numphotons; i++)
2760                         r_shadow_bouncegrid_state.photons_tasks[i].func(r_shadow_bouncegrid_state.photons_tasks + i);
2761                 r_shadow_bouncegrid_state.photons_done_task.done = 1;
2762         }
2763         t->done = 1;
2764 }
2765
2766 void R_Shadow_UpdateBounceGridTexture(void)
2767 {
2768         int flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
2769         r_shadow_bouncegrid_settings_t settings;
2770         qboolean enable = false;
2771         qboolean settingschanged;
2772
2773         enable = R_Shadow_BounceGrid_CheckEnable(flag);
2774         
2775         R_Shadow_BounceGrid_GenerateSettings(&settings);
2776         
2777         // changing intensity does not require an update
2778         r_shadow_bouncegrid_state.intensity = r_shadow_bouncegrid_intensity.value;
2779
2780         settingschanged = memcmp(&r_shadow_bouncegrid_state.settings, &settings, sizeof(settings)) != 0;
2781
2782         // when settings change, we free everything as it is just simpler that way.
2783         if (settingschanged || !enable)
2784         {
2785                 // not enabled, make sure we free anything we don't need anymore.
2786                 if (r_shadow_bouncegrid_state.texture)
2787                 {
2788                         R_FreeTexture(r_shadow_bouncegrid_state.texture);
2789                         r_shadow_bouncegrid_state.texture = NULL;
2790                 }
2791                 r_shadow_bouncegrid_state.highpixels = NULL;
2792                 if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
2793                 if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
2794                 if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
2795                 if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
2796                 if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
2797                 if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
2798                 if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
2799                 r_shadow_bouncegrid_state.numpixels = 0;
2800                 r_shadow_bouncegrid_state.numphotons = 0;
2801                 r_shadow_bouncegrid_state.directional = false;
2802
2803                 if (!enable)
2804                         return;
2805         }
2806
2807         // if all the settings seem identical to the previous update, return
2808         if (r_shadow_bouncegrid_state.texture && (settings.staticmode || realtime < r_shadow_bouncegrid_state.lastupdatetime + r_shadow_bouncegrid_dynamic_updateinterval.value) && !settingschanged)
2809                 return;
2810
2811         // store the new settings
2812         r_shadow_bouncegrid_state.settings = settings;
2813
2814         R_Shadow_BounceGrid_UpdateSpacing();
2815
2816         // allocate the highpixels array we'll be accumulating light into
2817         if (r_shadow_bouncegrid_state.blurpixels[0] == NULL)
2818                 r_shadow_bouncegrid_state.blurpixels[0] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2819         if (r_shadow_bouncegrid_state.settings.blur && r_shadow_bouncegrid_state.blurpixels[1] == NULL)
2820                 r_shadow_bouncegrid_state.blurpixels[1] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2821         r_shadow_bouncegrid_state.highpixels_index = 0;
2822         r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
2823
2824         // set up the tracking of photon data
2825         if (r_shadow_bouncegrid_state.photons == NULL)
2826                 r_shadow_bouncegrid_state.photons = (r_shadow_bouncegrid_photon_t *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.settings.maxphotons * sizeof(r_shadow_bouncegrid_photon_t));
2827         if (r_shadow_bouncegrid_state.photons_tasks == NULL)
2828                 r_shadow_bouncegrid_state.photons_tasks = (taskqueue_task_t *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.settings.maxphotons * sizeof(taskqueue_task_t));
2829         r_shadow_bouncegrid_state.numphotons = 0;
2830
2831         // set up the tracking of slice tasks
2832         if (r_shadow_bouncegrid_state.slices_tasks == NULL)
2833                 r_shadow_bouncegrid_state.slices_tasks = (taskqueue_task_t *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.resolution[2] * sizeof(taskqueue_task_t));
2834
2835         memset(&r_shadow_bouncegrid_state.cleartex_task, 0, sizeof(taskqueue_task_t));
2836         memset(&r_shadow_bouncegrid_state.assignphotons_task, 0, sizeof(taskqueue_task_t));
2837         memset(&r_shadow_bouncegrid_state.enqueuephotons_task, 0, sizeof(taskqueue_task_t));
2838         memset(r_shadow_bouncegrid_state.photons_tasks, 0, r_shadow_bouncegrid_state.settings.maxphotons * sizeof(taskqueue_task_t));
2839         memset(&r_shadow_bouncegrid_state.photons_done_task, 0, sizeof(taskqueue_task_t));
2840         memset(&r_shadow_bouncegrid_state.enqueue_slices_task, 0, sizeof(taskqueue_task_t));
2841         memset(r_shadow_bouncegrid_state.slices_tasks, 0, r_shadow_bouncegrid_state.resolution[2] * sizeof(taskqueue_task_t));
2842         memset(&r_shadow_bouncegrid_state.slices_done_task, 0, sizeof(taskqueue_task_t));
2843         memset(&r_shadow_bouncegrid_state.blurpixels_task, 0, sizeof(taskqueue_task_t));
2844
2845         // clear the texture
2846         TaskQueue_Setup(&r_shadow_bouncegrid_state.cleartex_task, NULL, R_Shadow_BounceGrid_ClearTex_Task, 0, 0, NULL, NULL);
2847         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.cleartex_task);
2848
2849         // calculate weighting factors for distributing photons among the lights
2850         TaskQueue_Setup(&r_shadow_bouncegrid_state.assignphotons_task, NULL, R_Shadow_BounceGrid_AssignPhotons_Task, 0, 0, NULL, NULL);
2851         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.assignphotons_task);
2852
2853         // enqueue tasks to trace the photons from lights
2854         TaskQueue_Setup(&r_shadow_bouncegrid_state.enqueuephotons_task, &r_shadow_bouncegrid_state.assignphotons_task, R_Shadow_BounceGrid_EnqueuePhotons_Task, 0, 0, NULL, NULL);
2855         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.enqueuephotons_task);
2856
2857         // accumulate the light paths into texture
2858         TaskQueue_Setup(&r_shadow_bouncegrid_state.enqueue_slices_task, &r_shadow_bouncegrid_state.photons_done_task, R_Shadow_BounceGrid_EnqueueSlices_Task, 0, 0, NULL, NULL);
2859         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.enqueue_slices_task);
2860
2861         // apply a mild blur filter to the texture
2862         TaskQueue_Setup(&r_shadow_bouncegrid_state.blurpixels_task, &r_shadow_bouncegrid_state.slices_done_task, R_Shadow_BounceGrid_BlurPixels_Task, 0, 0, NULL, NULL);
2863         TaskQueue_Enqueue(1, &r_shadow_bouncegrid_state.blurpixels_task);
2864
2865         TaskQueue_WaitForTaskDone(&r_shadow_bouncegrid_state.blurpixels_task);
2866         R_TimeReport("bouncegrid_gen");
2867
2868         // convert the pixels to lower precision and upload the texture
2869         // this unfortunately has to run on the main thread for OpenGL calls, so we have to block on the previous task...
2870         R_Shadow_BounceGrid_ConvertPixelsAndUpload();
2871         R_TimeReport("bouncegrid_tex");
2872
2873         // after we compute the static lighting we don't need to keep the highpixels array around
2874         if (settings.staticmode)
2875         {
2876                 r_shadow_bouncegrid_state.highpixels = NULL;
2877                 if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
2878                 if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
2879                 if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
2880                 if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
2881                 if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
2882                 if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
2883                 if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
2884         }
2885 }
2886
2887 void R_Shadow_RenderMode_VisibleLighting(qboolean transparent)
2888 {
2889         R_Shadow_RenderMode_Reset();
2890         GL_BlendFunc(GL_ONE, GL_ONE);
2891         GL_DepthRange(0, 1);
2892         GL_DepthTest(r_showlighting.integer < 2);
2893         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2894         if (!transparent)
2895                 GL_DepthFunc(GL_EQUAL);
2896         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2897 }
2898
2899 void R_Shadow_RenderMode_End(void)
2900 {
2901         R_Shadow_RenderMode_Reset();
2902         R_Shadow_RenderMode_ActiveLight(NULL);
2903         GL_DepthMask(true);
2904         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2905         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2906 }
2907
2908 int bboxedges[12][2] =
2909 {
2910         // top
2911         {0, 1}, // +X
2912         {0, 2}, // +Y
2913         {1, 3}, // Y, +X
2914         {2, 3}, // X, +Y
2915         // bottom
2916         {4, 5}, // +X
2917         {4, 6}, // +Y
2918         {5, 7}, // Y, +X
2919         {6, 7}, // X, +Y
2920         // verticals
2921         {0, 4}, // +Z
2922         {1, 5}, // X, +Z
2923         {2, 6}, // Y, +Z
2924         {3, 7}, // XY, +Z
2925 };
2926
2927 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2928 {
2929         if (!r_shadow_scissor.integer || r_shadow_usingdeferredprepass || r_trippy.integer)
2930         {
2931                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2932                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2933                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2934                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2935                 return false;
2936         }
2937         if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
2938                 return true; // invisible
2939         if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
2940         || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
2941         || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
2942         || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
2943                 r_refdef.stats[r_stat_lights_scissored]++;
2944         return false;
2945 }
2946
2947 static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2948 {
2949         // used to display how many times a surface is lit for level design purposes
2950         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
2951         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
2952         RSurf_DrawBatch();
2953 }
2954
2955 static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3])
2956 {
2957         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2958         R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
2959         RSurf_DrawBatch();
2960 }
2961
2962 extern cvar_t gl_lightmaps;
2963 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2964 {
2965         qboolean negated;
2966         float ambientcolor[3], diffusecolor[3], specularcolo