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