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