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