]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - r_shadow.c
Remove the model parameter from NativeContentsFromSuperContents/SuperContentsFromNati...
[xonotic/darkplaces.git] / r_shadow.c
1
2 /*
3 Terminology: Stencil Shadow Volume (sometimes called Stencil Shadows)
4 An extrusion of the lit faces, beginning at the original geometry and ending
5 further from the light source than the original geometry (presumably at least
6 as far as the light's radius, if the light has a radius at all), capped at
7 both front and back to avoid any problems (extrusion from dark faces also
8 works but has a different set of problems)
9
10 This is normally rendered using Carmack's Reverse technique, in which
11 backfaces behind zbuffer (zfail) increment the stencil, and frontfaces behind
12 zbuffer (zfail) decrement the stencil, the result is a stencil value of zero
13 where shadows did not intersect the visible geometry, suitable as a stencil
14 mask for rendering lighting everywhere but shadow.
15
16 In our case to hopefully avoid the Creative Labs patent, we draw the backfaces
17 as decrement and the frontfaces as increment, and we redefine the DepthFunc to
18 GL_LESS (the patent uses GL_GEQUAL) which causes zfail when behind surfaces
19 and zpass when infront (the patent draws where zpass with a GL_GEQUAL test),
20 additionally we clear stencil to 128 to avoid the need for the unclamped
21 incr/decr extension (not related to patent).
22
23 Patent warning:
24 This algorithm may be covered by Creative's patent (US Patent #6384822),
25 however that patent is quite specific about increment on backfaces and
26 decrement on frontfaces where zpass with GL_GEQUAL depth test, which is
27 opposite this implementation and partially opposite Carmack's Reverse paper
28 (which uses GL_LESS, but increments on backfaces and decrements on frontfaces).
29
30
31
32 Terminology: Stencil Light Volume (sometimes called Light Volumes)
33 Similar to a Stencil Shadow Volume, but inverted; rather than containing the
34 areas in shadow it contains the areas in light, this can only be built
35 quickly for certain limited cases (such as portal visibility from a point),
36 but is quite useful for some effects (sunlight coming from sky polygons is
37 one possible example, translucent occluders is another example).
38
39
40
41 Terminology: Optimized Stencil Shadow Volume
42 A Stencil Shadow Volume that has been processed sufficiently to ensure it has
43 no duplicate coverage of areas (no need to shadow an area twice), often this
44 greatly improves performance but is an operation too costly to use on moving
45 lights (however completely optimal Stencil Light Volumes can be constructed
46 in some ideal cases).
47
48
49
50 Terminology: Per Pixel Lighting (sometimes abbreviated PPL)
51 Per pixel evaluation of lighting equations, at a bare minimum this involves
52 DOT3 shading of diffuse lighting (per pixel dotproduct of negated incidence
53 vector and surface normal, using a texture of the surface bumps, called a
54 NormalMap) if supported by hardware; in our case there is support for cards
55 which are incapable of DOT3, the quality is quite poor however.  Additionally
56 it is desirable to have specular evaluation per pixel, per vertex
57 normalization of specular halfangle vectors causes noticable distortion but
58 is unavoidable on hardware without GL_ARB_fragment_program or
59 GL_ARB_fragment_shader.
60
61
62
63 Terminology: Normalization CubeMap
64 A cubemap containing normalized dot3-encoded (vectors of length 1 or less
65 encoded as RGB colors) for any possible direction, this technique allows per
66 pixel calculation of incidence vector for per pixel lighting purposes, which
67 would not otherwise be possible per pixel without GL_ARB_fragment_program or
68 GL_ARB_fragment_shader.
69
70
71
72 Terminology: 2D+1D Attenuation Texturing
73 A very crude approximation of light attenuation with distance which results
74 in cylindrical light shapes which fade vertically as a streak (some games
75 such as Doom3 allow this to be rotated to be less noticable in specific
76 cases), the technique is simply modulating lighting by two 2D textures (which
77 can be the same) on different axes of projection (XY and Z, typically), this
78 is the second best technique available without 3D Attenuation Texturing,
79 GL_ARB_fragment_program or GL_ARB_fragment_shader technology.
80
81
82
83 Terminology: 2D+1D Inverse Attenuation Texturing
84 A clever method described in papers on the Abducted engine, this has a squared
85 distance texture (bright on the outside, black in the middle), which is used
86 twice using GL_ADD blending, the result of this is used in an inverse modulate
87 (GL_ONE_MINUS_DST_ALPHA, GL_ZERO) to implement the equation
88 lighting*=(1-((X*X+Y*Y)+(Z*Z))) which is spherical (unlike 2D+1D attenuation
89 texturing).
90
91
92
93 Terminology: 3D Attenuation Texturing
94 A slightly crude approximation of light attenuation with distance, its flaws
95 are limited radius and resolution (performance tradeoffs).
96
97
98
99 Terminology: 3D Attenuation-Normalization Texturing
100 A 3D Attenuation Texture merged with a Normalization CubeMap, by making the
101 vectors shorter the lighting becomes darker, a very effective optimization of
102 diffuse lighting if 3D Attenuation Textures are already used.
103
104
105
106 Terminology: Light Cubemap Filtering
107 A technique for modeling non-uniform light distribution according to
108 direction, for example a lantern may use a cubemap to describe the light
109 emission pattern of the cage around the lantern (as well as soot buildup
110 discoloring the light in certain areas), often also used for softened grate
111 shadows and light shining through a stained glass window (done crudely by
112 texturing the lighting with a cubemap), another good example would be a disco
113 light.  This technique is used heavily in many games (Doom3 does not support
114 this however).
115
116
117
118 Terminology: Light Projection Filtering
119 A technique for modeling shadowing of light passing through translucent
120 surfaces, allowing stained glass windows and other effects to be done more
121 elegantly than possible with Light Cubemap Filtering by applying an occluder
122 texture to the lighting combined with a stencil light volume to limit the lit
123 area, this technique is used by Doom3 for spotlights and flashlights, among
124 other things, this can also be used more generally to render light passing
125 through multiple translucent occluders in a scene (using a light volume to
126 describe the area beyond the occluder, and thus mask off rendering of all
127 other areas).
128
129
130
131 Terminology: Doom3 Lighting
132 A combination of Stencil Shadow Volume, Per Pixel Lighting, Normalization
133 CubeMap, 2D+1D Attenuation Texturing, and Light Projection Filtering, as
134 demonstrated by the game Doom3.
135 */
136
137 #include "quakedef.h"
138 #include "r_shadow.h"
139 #include "cl_collision.h"
140 #include "portals.h"
141 #include "image.h"
142 #include "dpsoftrast.h"
143
144 #ifdef SUPPORTD3D
145 #include <d3d9.h>
146 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
147 #endif
148
149 static void R_Shadow_EditLights_Init(void);
150
151 typedef enum r_shadow_rendermode_e
152 {
153         R_SHADOW_RENDERMODE_NONE,
154         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
155         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
156         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
157         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
158         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
159         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
160         R_SHADOW_RENDERMODE_LIGHT_VERTEX,
161         R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN,
162         R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN,
163         R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN,
164         R_SHADOW_RENDERMODE_LIGHT_GLSL,
165         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
166         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
167         R_SHADOW_RENDERMODE_SHADOWMAP2D
168 }
169 r_shadow_rendermode_t;
170
171 typedef enum r_shadow_shadowmode_e
172 {
173         R_SHADOW_SHADOWMODE_STENCIL,
174         R_SHADOW_SHADOWMODE_SHADOWMAP2D
175 }
176 r_shadow_shadowmode_t;
177
178 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
179 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
180 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
181 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
182 int r_shadow_scenemaxlights;
183 int r_shadow_scenenumlights;
184 rtlight_t **r_shadow_scenelightlist; // includes both static lights and dlights, as filtered by appropriate flags
185 qboolean r_shadow_usingshadowmap2d;
186 qboolean r_shadow_usingshadowmaportho;
187 int r_shadow_shadowmapside;
188 float r_shadow_lightshadowmap_texturescale[4]; // xy = scale, zw = offset
189 float r_shadow_lightshadowmap_parameters[4]; // x = frustum width in pixels (excludes border), y = z scale, z = size of viewport, w = z center
190 float r_shadow_modelshadowmap_texturescale[4]; // xy = scale, zw = offset
191 float r_shadow_modelshadowmap_parameters[4]; // xyz = scale, w = shadow brightness
192 #if 0
193 int r_shadow_drawbuffer;
194 int r_shadow_readbuffer;
195 #endif
196 int r_shadow_cullface_front, r_shadow_cullface_back;
197 GLuint r_shadow_fbo2d;
198 r_shadow_shadowmode_t r_shadow_shadowmode;
199 int r_shadow_shadowmapfilterquality;
200 int r_shadow_shadowmapdepthbits;
201 int r_shadow_shadowmapmaxsize;
202 int r_shadow_shadowmaptexturesize;
203 qboolean r_shadow_shadowmapvsdct;
204 qboolean r_shadow_shadowmapsampler;
205 qboolean r_shadow_shadowmapshadowsampler;
206 int r_shadow_shadowmappcf;
207 int r_shadow_shadowmapborder;
208 matrix4x4_t r_shadow_shadowmapmatrix;
209 int r_shadow_lightscissor[4];
210 qboolean r_shadow_usingdeferredprepass;
211 qboolean r_shadow_shadowmapdepthtexture;
212 mod_alloclightmap_state_t r_shadow_shadowmapatlas_state;
213 int r_shadow_shadowmapatlas_modelshadows_x;
214 int r_shadow_shadowmapatlas_modelshadows_y;
215 int r_shadow_shadowmapatlas_modelshadows_size;
216 int maxshadowtriangles;
217 int *shadowelements;
218
219 int maxshadowvertices;
220 float *shadowvertex3f;
221
222 int maxshadowmark;
223 int numshadowmark;
224 int *shadowmark;
225 int *shadowmarklist;
226 int shadowmarkcount;
227
228 int maxshadowsides;
229 int numshadowsides;
230 unsigned char *shadowsides;
231 int *shadowsideslist;
232
233 int maxvertexupdate;
234 int *vertexupdate;
235 int *vertexremap;
236 int vertexupdatenum;
237
238 int r_shadow_buffer_numleafpvsbytes;
239 unsigned char *r_shadow_buffer_visitingleafpvs;
240 unsigned char *r_shadow_buffer_leafpvs;
241 int *r_shadow_buffer_leaflist;
242
243 int r_shadow_buffer_numsurfacepvsbytes;
244 unsigned char *r_shadow_buffer_surfacepvs;
245 int *r_shadow_buffer_surfacelist;
246 unsigned char *r_shadow_buffer_surfacesides;
247
248 int r_shadow_buffer_numshadowtrispvsbytes;
249 unsigned char *r_shadow_buffer_shadowtrispvs;
250 int r_shadow_buffer_numlighttrispvsbytes;
251 unsigned char *r_shadow_buffer_lighttrispvs;
252
253 rtexturepool_t *r_shadow_texturepool;
254 rtexture_t *r_shadow_attenuationgradienttexture;
255 rtexture_t *r_shadow_attenuation2dtexture;
256 rtexture_t *r_shadow_attenuation3dtexture;
257 skinframe_t *r_shadow_lightcorona;
258 rtexture_t *r_shadow_shadowmap2ddepthbuffer;
259 rtexture_t *r_shadow_shadowmap2ddepthtexture;
260 rtexture_t *r_shadow_shadowmapvsdcttexture;
261
262 GLuint r_shadow_prepassgeometryfbo;
263 GLuint r_shadow_prepasslightingdiffusespecularfbo;
264 GLuint r_shadow_prepasslightingdiffusefbo;
265 int r_shadow_prepass_width;
266 int r_shadow_prepass_height;
267 rtexture_t *r_shadow_prepassgeometrydepthbuffer;
268 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
269 rtexture_t *r_shadow_prepasslightingdiffusetexture;
270 rtexture_t *r_shadow_prepasslightingspeculartexture;
271
272 // keep track of the provided framebuffer info
273 static int r_shadow_fb_fbo;
274 static rtexture_t *r_shadow_fb_depthtexture;
275 static rtexture_t *r_shadow_fb_colortexture;
276
277 // lights are reloaded when this changes
278 char r_shadow_mapname[MAX_QPATH];
279
280 // buffer for doing corona fading
281 unsigned int r_shadow_occlusion_buf = 0;
282
283 // used only for light filters (cubemaps)
284 rtexturepool_t *r_shadow_filters_texturepool;
285
286 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"};
287 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"};
288 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
289 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"};
290 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)"};
291 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
292 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)"};
293 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"};
294 cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
295 cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
296 cvar_t r_shadow_gloss2exponent = {0, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
297 cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
298 cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
299 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
300 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
301 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
302 cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
303 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)"};
304 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
305 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
306 cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
307 cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
308 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)"};
309 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)"};
310 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"};
311 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
312 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
313 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"};
314 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)"};
315 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
316 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)"};
317 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes"};
318 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)"};
319 cvar_t r_shadow_shadowmapping_useshadowsampler = {CVAR_SAVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"};
320 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
321 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
322 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"};
323 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..."};
324 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"};
325 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"};
326 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
327 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
328 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "5", "shadowmap size bias for filtering"};
329 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
330 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
331 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
332 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
333 cvar_t r_shadow_sortsurfaces = {0, "r_shadow_sortsurfaces", "1", "improve performance by sorting illuminated surfaces by texture"};
334 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
335 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
336 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)"};
337 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"};
338 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"};
339 cvar_t r_shadow_culllights_trace_eyejitter = {CVAR_SAVE, "r_shadow_culllights_trace_eyejitter", "16", "offset eye location randomly by this much"};
340 cvar_t r_shadow_culllights_trace_enlarge = {CVAR_SAVE, "r_shadow_culllights_trace_enlarge", "0.1", "make light bounds bigger by *1.0+enlarge"};
341 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)"};
342 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)"};
343 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"};
344 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)"};
345 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"};
346 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"};
347 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" };
348 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)"};
349 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"};
350 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"};
351 cvar_t r_shadow_bouncegrid_dynamic_hitmodels = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_hitmodels", "0", "enables hitting character model geometry (SLOW)"};
352 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)"};
353 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)"};
354 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"};
355 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)"};
356 cvar_t r_shadow_bouncegrid_dynamic_spacing = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_spacing", "64", "unit size of bouncegrid pixel"};
357 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"};
358 cvar_t r_shadow_bouncegrid_dynamic_x = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_x", "64", "maximum texture size of bouncegrid on X axis"};
359 cvar_t r_shadow_bouncegrid_dynamic_y = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_y", "64", "maximum texture size of bouncegrid on Y axis"};
360 cvar_t r_shadow_bouncegrid_dynamic_z = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_z", "32", "maximum texture size of bouncegrid on Z axis"};
361 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"};
362 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)"};
363 cvar_t r_shadow_bouncegrid_intensity = {CVAR_SAVE, "r_shadow_bouncegrid_intensity", "4", "overall brightness of bouncegrid texture"};
364 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"};
365 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"};
366 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)" };
367 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"};
368 cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "0.25", "brightness of particles contributing to bouncegrid texture"};
369 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" };
370 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)" };
371 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"};
372 cvar_t r_shadow_bouncegrid_static = {CVAR_SAVE, "r_shadow_bouncegrid_static", "1", "use static radiosity solution (high quality) rather than dynamic (splotchy)"};
373 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" };
374 cvar_t r_shadow_bouncegrid_static_directionalshading = {CVAR_SAVE, "r_shadow_bouncegrid_static_directionalshading", "1", "whether to use directionalshading when in static mode"};
375 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"};
376 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"};
377 cvar_t r_shadow_bouncegrid_static_maxphotons = {CVAR_SAVE, "r_shadow_bouncegrid_static_maxphotons", "250000", "upper bound on photons in static mode"};
378 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)" };
379 cvar_t r_shadow_bouncegrid_static_spacing = {CVAR_SAVE, "r_shadow_bouncegrid_static_spacing", "64", "unit size of bouncegrid pixel when in static mode"};
380 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
381 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"};
382 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!"};
383 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
384 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
385 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
386 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
387 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
388 cvar_t r_editlights_cursorpushback = {0, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
389 cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
390 cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
391 cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
392 cvar_t r_editlights_drawproperties = {0, "r_editlights_drawproperties", "1", "draw properties of currently selected light"};
393 cvar_t r_editlights_current_origin = {0, "r_editlights_current_origin", "0 0 0", "origin of selected light"};
394 cvar_t r_editlights_current_angles = {0, "r_editlights_current_angles", "0 0 0", "angles of selected light"};
395 cvar_t r_editlights_current_color = {0, "r_editlights_current_color", "1 1 1", "color of selected light"};
396 cvar_t r_editlights_current_radius = {0, "r_editlights_current_radius", "0", "radius of selected light"};
397 cvar_t r_editlights_current_corona = {0, "r_editlights_current_corona", "0", "corona intensity of selected light"};
398 cvar_t r_editlights_current_coronasize = {0, "r_editlights_current_coronasize", "0", "corona size of selected light"};
399 cvar_t r_editlights_current_style = {0, "r_editlights_current_style", "0", "style of selected light"};
400 cvar_t r_editlights_current_shadows = {0, "r_editlights_current_shadows", "0", "shadows flag of selected light"};
401 cvar_t r_editlights_current_cubemap = {0, "r_editlights_current_cubemap", "0", "cubemap of selected light"};
402 cvar_t r_editlights_current_ambient = {0, "r_editlights_current_ambient", "0", "ambient intensity of selected light"};
403 cvar_t r_editlights_current_diffuse = {0, "r_editlights_current_diffuse", "1", "diffuse intensity of selected light"};
404 cvar_t r_editlights_current_specular = {0, "r_editlights_current_specular", "1", "specular intensity of selected light"};
405 cvar_t r_editlights_current_normalmode = {0, "r_editlights_current_normalmode", "0", "normalmode flag of selected light"};
406 cvar_t r_editlights_current_realtimemode = {0, "r_editlights_current_realtimemode", "0", "realtimemode flag of selected light"};
407
408 r_shadow_bouncegrid_state_t r_shadow_bouncegrid_state;
409
410 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
411 #define ATTENTABLESIZE 256
412 // 1D gradient, 2D circle and 3D sphere attenuation textures
413 #define ATTEN1DSIZE 32
414 #define ATTEN2DSIZE 64
415 #define ATTEN3DSIZE 32
416
417 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
418 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
419 static float r_shadow_attentable[ATTENTABLESIZE+1];
420
421 rtlight_t *r_shadow_compilingrtlight;
422 static memexpandablearray_t r_shadow_worldlightsarray;
423 dlight_t *r_shadow_selectedlight;
424 dlight_t r_shadow_bufferlight;
425 vec3_t r_editlights_cursorlocation;
426 qboolean r_editlights_lockcursor;
427
428 extern int con_vislines;
429
430 void R_Shadow_UncompileWorldLights(void);
431 void R_Shadow_ClearWorldLights(void);
432 void R_Shadow_SaveWorldLights(void);
433 void R_Shadow_LoadWorldLights(void);
434 void R_Shadow_LoadLightsFile(void);
435 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
436 void R_Shadow_EditLights_Reload_f(void);
437 void R_Shadow_ValidateCvars(void);
438 static void R_Shadow_MakeTextures(void);
439
440 #define EDLIGHTSPRSIZE                  8
441 skinframe_t *r_editlights_sprcursor;
442 skinframe_t *r_editlights_sprlight;
443 skinframe_t *r_editlights_sprnoshadowlight;
444 skinframe_t *r_editlights_sprcubemaplight;
445 skinframe_t *r_editlights_sprcubemapnoshadowlight;
446 skinframe_t *r_editlights_sprselection;
447
448 static void R_Shadow_DrawModelShadowMaps(void);
449 static void R_Shadow_MakeShadowMap(int texturesize);
450 static void R_Shadow_MakeVSDCT(void);
451 static void R_Shadow_SetShadowMode(void)
452 {
453         r_shadow_shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
454         r_shadow_shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
455         r_shadow_shadowmapmaxsize = bound(r_shadow_shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, r_shadow_shadowmaptexturesize / 8);
456         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20;
457         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
458         r_shadow_shadowmapshadowsampler = r_shadow_shadowmapping_useshadowsampler.integer != 0;
459         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
460         r_shadow_shadowmapsampler = false;
461         r_shadow_shadowmappcf = 0;
462         r_shadow_shadowmapdepthtexture = r_fb.usedepthtextures;
463         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
464         Mod_AllocLightmap_Init(&r_shadow_shadowmapatlas_state, r_main_mempool, r_shadow_shadowmaptexturesize, r_shadow_shadowmaptexturesize);
465         if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
466         {
467                 switch(vid.renderpath)
468                 {
469                 case RENDERPATH_GL20:
470                         if(r_shadow_shadowmapfilterquality < 0)
471                         {
472                                 if (!r_fb.usedepthtextures)
473                                         r_shadow_shadowmappcf = 1;
474                                 else if((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && vid.support.arb_shadow && r_shadow_shadowmapshadowsampler)
475                                 {
476                                         r_shadow_shadowmapsampler = true;
477                                         r_shadow_shadowmappcf = 1;
478                                 }
479                                 else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
480                                         r_shadow_shadowmappcf = 1;
481                                 else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
482                                         r_shadow_shadowmappcf = 1;
483                                 else
484                                         r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
485                         }
486                         else
487                         {
488                 r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
489                                 switch (r_shadow_shadowmapfilterquality)
490                                 {
491                                 case 1:
492                                         break;
493                                 case 2:
494                                         r_shadow_shadowmappcf = 1;
495                                         break;
496                                 case 3:
497                                         r_shadow_shadowmappcf = 1;
498                                         break;
499                                 case 4:
500                                         r_shadow_shadowmappcf = 2;
501                                         break;
502                                 }
503                         }
504                         if (!r_fb.usedepthtextures)
505                                 r_shadow_shadowmapsampler = false;
506                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
507                         break;
508                 case RENDERPATH_D3D9:
509                 case RENDERPATH_D3D10:
510                 case RENDERPATH_D3D11:
511                 case RENDERPATH_SOFT:
512                         r_shadow_shadowmapsampler = false;
513                         r_shadow_shadowmappcf = 1;
514                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
515                         break;
516                 case RENDERPATH_GL11:
517                 case RENDERPATH_GL13:
518                 case RENDERPATH_GLES1:
519                 case RENDERPATH_GLES2:
520                         break;
521                 }
522         }
523
524         if(R_CompileShader_CheckStaticParms())
525                 R_GLSL_Restart_f();
526 }
527
528 qboolean R_Shadow_ShadowMappingEnabled(void)
529 {
530         switch (r_shadow_shadowmode)
531         {
532         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
533                 return true;
534         default:
535                 return false;
536         }
537 }
538
539 static void R_Shadow_FreeShadowMaps(void)
540 {
541         Mod_AllocLightmap_Free(&r_shadow_shadowmapatlas_state);
542
543         R_Shadow_SetShadowMode();
544
545         R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d);
546
547         r_shadow_fbo2d = 0;
548
549         if (r_shadow_shadowmap2ddepthtexture)
550                 R_FreeTexture(r_shadow_shadowmap2ddepthtexture);
551         r_shadow_shadowmap2ddepthtexture = NULL;
552
553         if (r_shadow_shadowmap2ddepthbuffer)
554                 R_FreeTexture(r_shadow_shadowmap2ddepthbuffer);
555         r_shadow_shadowmap2ddepthbuffer = NULL;
556
557         if (r_shadow_shadowmapvsdcttexture)
558                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
559         r_shadow_shadowmapvsdcttexture = NULL;
560 }
561
562 static void r_shadow_start(void)
563 {
564         // allocate vertex processing arrays
565         memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state));
566         r_shadow_attenuationgradienttexture = NULL;
567         r_shadow_attenuation2dtexture = NULL;
568         r_shadow_attenuation3dtexture = NULL;
569         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
570         r_shadow_shadowmap2ddepthtexture = NULL;
571         r_shadow_shadowmap2ddepthbuffer = NULL;
572         r_shadow_shadowmapvsdcttexture = NULL;
573         r_shadow_shadowmapmaxsize = 0;
574         r_shadow_shadowmaptexturesize = 0;
575         r_shadow_shadowmapfilterquality = -1;
576         r_shadow_shadowmapdepthbits = 0;
577         r_shadow_shadowmapvsdct = false;
578         r_shadow_shadowmapsampler = false;
579         r_shadow_shadowmappcf = 0;
580         r_shadow_fbo2d = 0;
581
582         R_Shadow_FreeShadowMaps();
583
584         r_shadow_texturepool = NULL;
585         r_shadow_filters_texturepool = NULL;
586         R_Shadow_ValidateCvars();
587         R_Shadow_MakeTextures();
588         r_shadow_scenemaxlights = 0;
589         r_shadow_scenenumlights = 0;
590         r_shadow_scenelightlist = NULL;
591         maxshadowtriangles = 0;
592         shadowelements = NULL;
593         maxshadowvertices = 0;
594         shadowvertex3f = NULL;
595         maxvertexupdate = 0;
596         vertexupdate = NULL;
597         vertexremap = NULL;
598         vertexupdatenum = 0;
599         maxshadowmark = 0;
600         numshadowmark = 0;
601         shadowmark = NULL;
602         shadowmarklist = NULL;
603         shadowmarkcount = 0;
604         maxshadowsides = 0;
605         numshadowsides = 0;
606         shadowsides = NULL;
607         shadowsideslist = NULL;
608         r_shadow_buffer_numleafpvsbytes = 0;
609         r_shadow_buffer_visitingleafpvs = NULL;
610         r_shadow_buffer_leafpvs = NULL;
611         r_shadow_buffer_leaflist = NULL;
612         r_shadow_buffer_numsurfacepvsbytes = 0;
613         r_shadow_buffer_surfacepvs = NULL;
614         r_shadow_buffer_surfacelist = NULL;
615         r_shadow_buffer_surfacesides = NULL;
616         r_shadow_buffer_numshadowtrispvsbytes = 0;
617         r_shadow_buffer_shadowtrispvs = NULL;
618         r_shadow_buffer_numlighttrispvsbytes = 0;
619         r_shadow_buffer_lighttrispvs = NULL;
620
621         r_shadow_usingdeferredprepass = false;
622         r_shadow_prepass_width = r_shadow_prepass_height = 0;
623
624         // determine renderpath specific capabilities, we don't need to figure
625         // these out per frame...
626         switch(vid.renderpath)
627         {
628         case RENDERPATH_GL20:
629                 r_shadow_bouncegrid_state.allowdirectionalshading = true;
630                 r_shadow_bouncegrid_state.capable = vid.support.ext_texture_3d;
631                 break;
632         case RENDERPATH_GLES2:
633                 // for performance reasons, do not use directional shading on GLES devices
634                 r_shadow_bouncegrid_state.capable = vid.support.ext_texture_3d;
635                 break;
636                 // these renderpaths do not currently have the code to display the bouncegrid, so disable it on them...
637         case RENDERPATH_GL11:
638         case RENDERPATH_GL13:
639         case RENDERPATH_GLES1:
640         case RENDERPATH_SOFT:
641         case RENDERPATH_D3D9:
642         case RENDERPATH_D3D10:
643         case RENDERPATH_D3D11:
644                 break;
645         }
646 }
647
648 static void R_Shadow_FreeDeferred(void);
649 static void r_shadow_shutdown(void)
650 {
651         CHECKGLERROR
652         R_Shadow_UncompileWorldLights();
653
654         R_Shadow_FreeShadowMaps();
655
656         r_shadow_usingdeferredprepass = false;
657         if (r_shadow_prepass_width)
658                 R_Shadow_FreeDeferred();
659         r_shadow_prepass_width = r_shadow_prepass_height = 0;
660
661         CHECKGLERROR
662         r_shadow_scenemaxlights = 0;
663         r_shadow_scenenumlights = 0;
664         if (r_shadow_scenelightlist)
665                 Mem_Free(r_shadow_scenelightlist);
666         r_shadow_scenelightlist = NULL;
667         r_shadow_bouncegrid_state.highpixels = NULL;
668         if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
669         if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
670         if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
671         if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
672         if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
673         r_shadow_bouncegrid_state.maxsplatpaths = 0;
674         memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state));
675         r_shadow_attenuationgradienttexture = NULL;
676         r_shadow_attenuation2dtexture = NULL;
677         r_shadow_attenuation3dtexture = NULL;
678         R_FreeTexturePool(&r_shadow_texturepool);
679         R_FreeTexturePool(&r_shadow_filters_texturepool);
680         maxshadowtriangles = 0;
681         if (shadowelements)
682                 Mem_Free(shadowelements);
683         shadowelements = NULL;
684         if (shadowvertex3f)
685                 Mem_Free(shadowvertex3f);
686         shadowvertex3f = NULL;
687         maxvertexupdate = 0;
688         if (vertexupdate)
689                 Mem_Free(vertexupdate);
690         vertexupdate = NULL;
691         if (vertexremap)
692                 Mem_Free(vertexremap);
693         vertexremap = NULL;
694         vertexupdatenum = 0;
695         maxshadowmark = 0;
696         numshadowmark = 0;
697         if (shadowmark)
698                 Mem_Free(shadowmark);
699         shadowmark = NULL;
700         if (shadowmarklist)
701                 Mem_Free(shadowmarklist);
702         shadowmarklist = NULL;
703         shadowmarkcount = 0;
704         maxshadowsides = 0;
705         numshadowsides = 0;
706         if (shadowsides)
707                 Mem_Free(shadowsides);
708         shadowsides = NULL;
709         if (shadowsideslist)
710                 Mem_Free(shadowsideslist);
711         shadowsideslist = NULL;
712         r_shadow_buffer_numleafpvsbytes = 0;
713         if (r_shadow_buffer_visitingleafpvs)
714                 Mem_Free(r_shadow_buffer_visitingleafpvs);
715         r_shadow_buffer_visitingleafpvs = NULL;
716         if (r_shadow_buffer_leafpvs)
717                 Mem_Free(r_shadow_buffer_leafpvs);
718         r_shadow_buffer_leafpvs = NULL;
719         if (r_shadow_buffer_leaflist)
720                 Mem_Free(r_shadow_buffer_leaflist);
721         r_shadow_buffer_leaflist = NULL;
722         r_shadow_buffer_numsurfacepvsbytes = 0;
723         if (r_shadow_buffer_surfacepvs)
724                 Mem_Free(r_shadow_buffer_surfacepvs);
725         r_shadow_buffer_surfacepvs = NULL;
726         if (r_shadow_buffer_surfacelist)
727                 Mem_Free(r_shadow_buffer_surfacelist);
728         r_shadow_buffer_surfacelist = NULL;
729         if (r_shadow_buffer_surfacesides)
730                 Mem_Free(r_shadow_buffer_surfacesides);
731         r_shadow_buffer_surfacesides = NULL;
732         r_shadow_buffer_numshadowtrispvsbytes = 0;
733         if (r_shadow_buffer_shadowtrispvs)
734                 Mem_Free(r_shadow_buffer_shadowtrispvs);
735         r_shadow_buffer_numlighttrispvsbytes = 0;
736         if (r_shadow_buffer_lighttrispvs)
737                 Mem_Free(r_shadow_buffer_lighttrispvs);
738 }
739
740 static void r_shadow_newmap(void)
741 {
742         r_shadow_bouncegrid_state.highpixels = NULL;
743         if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
744         if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
745         if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
746         if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
747         if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
748         r_shadow_bouncegrid_state.maxsplatpaths = 0;
749         if (r_shadow_bouncegrid_state.texture)    R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL;
750         if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
751         if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
752         if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
753         if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
754         if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
755         if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
756         if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
757         if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
758                 R_Shadow_EditLights_Reload_f();
759 }
760
761 void R_Shadow_Init(void)
762 {
763         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
764         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
765         Cvar_RegisterVariable(&r_shadow_usebihculling);
766         Cvar_RegisterVariable(&r_shadow_usenormalmap);
767         Cvar_RegisterVariable(&r_shadow_debuglight);
768         Cvar_RegisterVariable(&r_shadow_deferred);
769         Cvar_RegisterVariable(&r_shadow_gloss);
770         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
771         Cvar_RegisterVariable(&r_shadow_glossintensity);
772         Cvar_RegisterVariable(&r_shadow_glossexponent);
773         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
774         Cvar_RegisterVariable(&r_shadow_glossexact);
775         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
776         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
777         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
778         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
779         Cvar_RegisterVariable(&r_shadow_projectdistance);
780         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
781         Cvar_RegisterVariable(&r_shadow_realtime_world_importlightentitiesfrommap);
782         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
783         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
784         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
785         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
786         Cvar_RegisterVariable(&r_shadow_realtime_world);
787         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
788         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
789         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
790         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
791         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
792         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
793         Cvar_RegisterVariable(&r_shadow_scissor);
794         Cvar_RegisterVariable(&r_shadow_shadowmapping);
795         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
796         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
797         Cvar_RegisterVariable(&r_shadow_shadowmapping_useshadowsampler);
798         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
799         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
800         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
801         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
802         Cvar_RegisterVariable(&r_shadow_shadowmapping_texturesize);
803 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
804 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
805         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
806         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
807         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
808         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
809         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
810         Cvar_RegisterVariable(&r_shadow_sortsurfaces);
811         Cvar_RegisterVariable(&r_shadow_polygonfactor);
812         Cvar_RegisterVariable(&r_shadow_polygonoffset);
813         Cvar_RegisterVariable(&r_shadow_texture3d);
814         Cvar_RegisterVariable(&r_shadow_culllights_pvs);
815         Cvar_RegisterVariable(&r_shadow_culllights_trace);
816         Cvar_RegisterVariable(&r_shadow_culllights_trace_eyejitter);
817         Cvar_RegisterVariable(&r_shadow_culllights_trace_enlarge);
818         Cvar_RegisterVariable(&r_shadow_culllights_trace_samples);
819         Cvar_RegisterVariable(&r_shadow_culllights_trace_tempsamples);
820         Cvar_RegisterVariable(&r_shadow_culllights_trace_delay);
821         Cvar_RegisterVariable(&r_shadow_bouncegrid);
822         Cvar_RegisterVariable(&r_shadow_bouncegrid_blur);
823         Cvar_RegisterVariable(&r_shadow_bouncegrid_bounceanglediffuse);
824         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_bounceminimumintensity);
825         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_culllightpaths);
826         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_directionalshading);
827         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_dlightparticlemultiplier);
828         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_hitmodels);
829         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_lightradiusscale);
830         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_maxbounce);
831         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_maxphotons);
832         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_quality);
833         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_spacing);
834         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_updateinterval);
835         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_x);
836         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_y);
837         Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_z);
838         Cvar_RegisterVariable(&r_shadow_bouncegrid_floatcolors);
839         Cvar_RegisterVariable(&r_shadow_bouncegrid_includedirectlighting);
840         Cvar_RegisterVariable(&r_shadow_bouncegrid_intensity);
841         Cvar_RegisterVariable(&r_shadow_bouncegrid_lightpathsize_conespread);
842         Cvar_RegisterVariable(&r_shadow_bouncegrid_lightpathsize_initial);
843         Cvar_RegisterVariable(&r_shadow_bouncegrid_normalizevectors);
844         Cvar_RegisterVariable(&r_shadow_bouncegrid_particlebounceintensity);
845         Cvar_RegisterVariable(&r_shadow_bouncegrid_particleintensity);
846         Cvar_RegisterVariable(&r_shadow_bouncegrid_rng_seed);
847         Cvar_RegisterVariable(&r_shadow_bouncegrid_rng_type);
848         Cvar_RegisterVariable(&r_shadow_bouncegrid_sortlightpaths);
849         Cvar_RegisterVariable(&r_shadow_bouncegrid_static);
850         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_bounceminimumintensity);
851         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_directionalshading);
852         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_lightradiusscale);
853         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxbounce);
854         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxphotons);
855         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_quality);
856         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_spacing);
857         Cvar_RegisterVariable(&r_coronas);
858         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
859         Cvar_RegisterVariable(&r_coronas_occlusionquery);
860         Cvar_RegisterVariable(&gl_flashblend);
861         Cvar_RegisterVariable(&gl_ext_separatestencil);
862         Cvar_RegisterVariable(&gl_ext_stenciltwoside);
863         R_Shadow_EditLights_Init();
864         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
865         r_shadow_scenemaxlights = 0;
866         r_shadow_scenenumlights = 0;
867         r_shadow_scenelightlist = NULL;
868         maxshadowtriangles = 0;
869         shadowelements = NULL;
870         maxshadowvertices = 0;
871         shadowvertex3f = NULL;
872         maxvertexupdate = 0;
873         vertexupdate = NULL;
874         vertexremap = NULL;
875         vertexupdatenum = 0;
876         maxshadowmark = 0;
877         numshadowmark = 0;
878         shadowmark = NULL;
879         shadowmarklist = NULL;
880         shadowmarkcount = 0;
881         maxshadowsides = 0;
882         numshadowsides = 0;
883         shadowsides = NULL;
884         shadowsideslist = NULL;
885         r_shadow_buffer_numleafpvsbytes = 0;
886         r_shadow_buffer_visitingleafpvs = NULL;
887         r_shadow_buffer_leafpvs = NULL;
888         r_shadow_buffer_leaflist = NULL;
889         r_shadow_buffer_numsurfacepvsbytes = 0;
890         r_shadow_buffer_surfacepvs = NULL;
891         r_shadow_buffer_surfacelist = NULL;
892         r_shadow_buffer_surfacesides = NULL;
893         r_shadow_buffer_shadowtrispvs = NULL;
894         r_shadow_buffer_lighttrispvs = NULL;
895         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap, NULL, NULL);
896 }
897
898 matrix4x4_t matrix_attenuationxyz =
899 {
900         {
901                 {0.5, 0.0, 0.0, 0.5},
902                 {0.0, 0.5, 0.0, 0.5},
903                 {0.0, 0.0, 0.5, 0.5},
904                 {0.0, 0.0, 0.0, 1.0}
905         }
906 };
907
908 matrix4x4_t matrix_attenuationz =
909 {
910         {
911                 {0.0, 0.0, 0.5, 0.5},
912                 {0.0, 0.0, 0.0, 0.5},
913                 {0.0, 0.0, 0.0, 0.5},
914                 {0.0, 0.0, 0.0, 1.0}
915         }
916 };
917
918 static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
919 {
920         numvertices = ((numvertices + 255) & ~255) * vertscale;
921         numtriangles = ((numtriangles + 255) & ~255) * triscale;
922         // make sure shadowelements is big enough for this volume
923         if (maxshadowtriangles < numtriangles)
924         {
925                 maxshadowtriangles = numtriangles;
926                 if (shadowelements)
927                         Mem_Free(shadowelements);
928                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
929         }
930         // make sure shadowvertex3f is big enough for this volume
931         if (maxshadowvertices < numvertices)
932         {
933                 maxshadowvertices = numvertices;
934                 if (shadowvertex3f)
935                         Mem_Free(shadowvertex3f);
936                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
937         }
938 }
939
940 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
941 {
942         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
943         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
944         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
945         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
946         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
947         {
948                 if (r_shadow_buffer_visitingleafpvs)
949                         Mem_Free(r_shadow_buffer_visitingleafpvs);
950                 if (r_shadow_buffer_leafpvs)
951                         Mem_Free(r_shadow_buffer_leafpvs);
952                 if (r_shadow_buffer_leaflist)
953                         Mem_Free(r_shadow_buffer_leaflist);
954                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
955                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
956                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
957                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
958         }
959         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
960         {
961                 if (r_shadow_buffer_surfacepvs)
962                         Mem_Free(r_shadow_buffer_surfacepvs);
963                 if (r_shadow_buffer_surfacelist)
964                         Mem_Free(r_shadow_buffer_surfacelist);
965                 if (r_shadow_buffer_surfacesides)
966                         Mem_Free(r_shadow_buffer_surfacesides);
967                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
968                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
969                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
970                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
971         }
972         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
973         {
974                 if (r_shadow_buffer_shadowtrispvs)
975                         Mem_Free(r_shadow_buffer_shadowtrispvs);
976                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
977                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
978         }
979         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
980         {
981                 if (r_shadow_buffer_lighttrispvs)
982                         Mem_Free(r_shadow_buffer_lighttrispvs);
983                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
984                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
985         }
986 }
987
988 void R_Shadow_PrepareShadowMark(int numtris)
989 {
990         // make sure shadowmark is big enough for this volume
991         if (maxshadowmark < numtris)
992         {
993                 maxshadowmark = numtris;
994                 if (shadowmark)
995                         Mem_Free(shadowmark);
996                 if (shadowmarklist)
997                         Mem_Free(shadowmarklist);
998                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
999                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
1000                 shadowmarkcount = 0;
1001         }
1002         shadowmarkcount++;
1003         // if shadowmarkcount wrapped we clear the array and adjust accordingly
1004         if (shadowmarkcount == 0)
1005         {
1006                 shadowmarkcount = 1;
1007                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
1008         }
1009         numshadowmark = 0;
1010 }
1011
1012 void R_Shadow_PrepareShadowSides(int numtris)
1013 {
1014         if (maxshadowsides < numtris)
1015         {
1016                 maxshadowsides = numtris;
1017                 if (shadowsides)
1018                         Mem_Free(shadowsides);
1019                 if (shadowsideslist)
1020                         Mem_Free(shadowsideslist);
1021                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
1022                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
1023         }
1024         numshadowsides = 0;
1025 }
1026
1027 static int R_Shadow_ConstructShadowVolume_ZFail(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
1028 {
1029         int i, j;
1030         int outtriangles = 0, outvertices = 0;
1031         const int *element;
1032         const float *vertex;
1033         float ratio, direction[3], projectvector[3];
1034
1035         if (projectdirection)
1036                 VectorScale(projectdirection, projectdistance, projectvector);
1037         else
1038                 VectorClear(projectvector);
1039
1040         // create the vertices
1041         if (projectdirection)
1042         {
1043                 for (i = 0;i < numshadowmarktris;i++)
1044                 {
1045                         element = inelement3i + shadowmarktris[i] * 3;
1046                         for (j = 0;j < 3;j++)
1047                         {
1048                                 if (vertexupdate[element[j]] != vertexupdatenum)
1049                                 {
1050                                         vertexupdate[element[j]] = vertexupdatenum;
1051                                         vertexremap[element[j]] = outvertices;
1052                                         vertex = invertex3f + element[j] * 3;
1053                                         // project one copy of the vertex according to projectvector
1054                                         VectorCopy(vertex, outvertex3f);
1055                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1056                                         outvertex3f += 6;
1057                                         outvertices += 2;
1058                                 }
1059                         }
1060                 }
1061         }
1062         else
1063         {
1064                 for (i = 0;i < numshadowmarktris;i++)
1065                 {
1066                         element = inelement3i + shadowmarktris[i] * 3;
1067                         for (j = 0;j < 3;j++)
1068                         {
1069                                 if (vertexupdate[element[j]] != vertexupdatenum)
1070                                 {
1071                                         vertexupdate[element[j]] = vertexupdatenum;
1072                                         vertexremap[element[j]] = outvertices;
1073                                         vertex = invertex3f + element[j] * 3;
1074                                         // project one copy of the vertex to the sphere radius of the light
1075                                         // (FIXME: would projecting it to the light box be better?)
1076                                         VectorSubtract(vertex, projectorigin, direction);
1077                                         ratio = projectdistance / VectorLength(direction);
1078                                         VectorCopy(vertex, outvertex3f);
1079                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1080                                         outvertex3f += 6;
1081                                         outvertices += 2;
1082                                 }
1083                         }
1084                 }
1085         }
1086
1087         if (r_shadow_frontsidecasting.integer)
1088         {
1089                 for (i = 0;i < numshadowmarktris;i++)
1090                 {
1091                         int remappedelement[3];
1092                         int markindex;
1093                         const int *neighbortriangle;
1094
1095                         markindex = shadowmarktris[i] * 3;
1096                         element = inelement3i + markindex;
1097                         neighbortriangle = inneighbor3i + markindex;
1098                         // output the front and back triangles
1099                         outelement3i[0] = vertexremap[element[0]];
1100                         outelement3i[1] = vertexremap[element[1]];
1101                         outelement3i[2] = vertexremap[element[2]];
1102                         outelement3i[3] = vertexremap[element[2]] + 1;
1103                         outelement3i[4] = vertexremap[element[1]] + 1;
1104                         outelement3i[5] = vertexremap[element[0]] + 1;
1105
1106                         outelement3i += 6;
1107                         outtriangles += 2;
1108                         // output the sides (facing outward from this triangle)
1109                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1110                         {
1111                                 remappedelement[0] = vertexremap[element[0]];
1112                                 remappedelement[1] = vertexremap[element[1]];
1113                                 outelement3i[0] = remappedelement[1];
1114                                 outelement3i[1] = remappedelement[0];
1115                                 outelement3i[2] = remappedelement[0] + 1;
1116                                 outelement3i[3] = remappedelement[1];
1117                                 outelement3i[4] = remappedelement[0] + 1;
1118                                 outelement3i[5] = remappedelement[1] + 1;
1119
1120                                 outelement3i += 6;
1121                                 outtriangles += 2;
1122                         }
1123                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1124                         {
1125                                 remappedelement[1] = vertexremap[element[1]];
1126                                 remappedelement[2] = vertexremap[element[2]];
1127                                 outelement3i[0] = remappedelement[2];
1128                                 outelement3i[1] = remappedelement[1];
1129                                 outelement3i[2] = remappedelement[1] + 1;
1130                                 outelement3i[3] = remappedelement[2];
1131                                 outelement3i[4] = remappedelement[1] + 1;
1132                                 outelement3i[5] = remappedelement[2] + 1;
1133
1134                                 outelement3i += 6;
1135                                 outtriangles += 2;
1136                         }
1137                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1138                         {
1139                                 remappedelement[0] = vertexremap[element[0]];
1140                                 remappedelement[2] = vertexremap[element[2]];
1141                                 outelement3i[0] = remappedelement[0];
1142                                 outelement3i[1] = remappedelement[2];
1143                                 outelement3i[2] = remappedelement[2] + 1;
1144                                 outelement3i[3] = remappedelement[0];
1145                                 outelement3i[4] = remappedelement[2] + 1;
1146                                 outelement3i[5] = remappedelement[0] + 1;
1147
1148                                 outelement3i += 6;
1149                                 outtriangles += 2;
1150                         }
1151                 }
1152         }
1153         else
1154         {
1155                 for (i = 0;i < numshadowmarktris;i++)
1156                 {
1157                         int remappedelement[3];
1158                         int markindex;
1159                         const int *neighbortriangle;
1160
1161                         markindex = shadowmarktris[i] * 3;
1162                         element = inelement3i + markindex;
1163                         neighbortriangle = inneighbor3i + markindex;
1164                         // output the front and back triangles
1165                         outelement3i[0] = vertexremap[element[2]];
1166                         outelement3i[1] = vertexremap[element[1]];
1167                         outelement3i[2] = vertexremap[element[0]];
1168                         outelement3i[3] = vertexremap[element[0]] + 1;
1169                         outelement3i[4] = vertexremap[element[1]] + 1;
1170                         outelement3i[5] = vertexremap[element[2]] + 1;
1171
1172                         outelement3i += 6;
1173                         outtriangles += 2;
1174                         // output the sides (facing outward from this triangle)
1175                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1176                         {
1177                                 remappedelement[0] = vertexremap[element[0]];
1178                                 remappedelement[1] = vertexremap[element[1]];
1179                                 outelement3i[0] = remappedelement[0];
1180                                 outelement3i[1] = remappedelement[1];
1181                                 outelement3i[2] = remappedelement[1] + 1;
1182                                 outelement3i[3] = remappedelement[0];
1183                                 outelement3i[4] = remappedelement[1] + 1;
1184                                 outelement3i[5] = remappedelement[0] + 1;
1185
1186                                 outelement3i += 6;
1187                                 outtriangles += 2;
1188                         }
1189                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1190                         {
1191                                 remappedelement[1] = vertexremap[element[1]];
1192                                 remappedelement[2] = vertexremap[element[2]];
1193                                 outelement3i[0] = remappedelement[1];
1194                                 outelement3i[1] = remappedelement[2];
1195                                 outelement3i[2] = remappedelement[2] + 1;
1196                                 outelement3i[3] = remappedelement[1];
1197                                 outelement3i[4] = remappedelement[2] + 1;
1198                                 outelement3i[5] = remappedelement[1] + 1;
1199
1200                                 outelement3i += 6;
1201                                 outtriangles += 2;
1202                         }
1203                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1204                         {
1205                                 remappedelement[0] = vertexremap[element[0]];
1206                                 remappedelement[2] = vertexremap[element[2]];
1207                                 outelement3i[0] = remappedelement[2];
1208                                 outelement3i[1] = remappedelement[0];
1209                                 outelement3i[2] = remappedelement[0] + 1;
1210                                 outelement3i[3] = remappedelement[2];
1211                                 outelement3i[4] = remappedelement[0] + 1;
1212                                 outelement3i[5] = remappedelement[2] + 1;
1213
1214                                 outelement3i += 6;
1215                                 outtriangles += 2;
1216                         }
1217                 }
1218         }
1219         if (outnumvertices)
1220                 *outnumvertices = outvertices;
1221         return outtriangles;
1222 }
1223
1224 static int R_Shadow_ConstructShadowVolume_ZPass(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
1225 {
1226         int i, j, k;
1227         int outtriangles = 0, outvertices = 0;
1228         const int *element;
1229         const float *vertex;
1230         float ratio, direction[3], projectvector[3];
1231         qboolean side[4];
1232
1233         if (projectdirection)
1234                 VectorScale(projectdirection, projectdistance, projectvector);
1235         else
1236                 VectorClear(projectvector);
1237
1238         for (i = 0;i < numshadowmarktris;i++)
1239         {
1240                 int remappedelement[3];
1241                 int markindex;
1242                 const int *neighbortriangle;
1243
1244                 markindex = shadowmarktris[i] * 3;
1245                 neighbortriangle = inneighbor3i + markindex;
1246                 side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
1247                 side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
1248                 side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
1249                 if (side[0] + side[1] + side[2] == 0)
1250                         continue;
1251
1252                 side[3] = side[0];
1253                 element = inelement3i + markindex;
1254
1255                 // create the vertices
1256                 for (j = 0;j < 3;j++)
1257                 {
1258                         if (side[j] + side[j+1] == 0)
1259                                 continue;
1260                         k = element[j];
1261                         if (vertexupdate[k] != vertexupdatenum)
1262                         {
1263                                 vertexupdate[k] = vertexupdatenum;
1264                                 vertexremap[k] = outvertices;
1265                                 vertex = invertex3f + k * 3;
1266                                 VectorCopy(vertex, outvertex3f);
1267                                 if (projectdirection)
1268                                 {
1269                                         // project one copy of the vertex according to projectvector
1270                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1271                                 }
1272                                 else
1273                                 {
1274                                         // project one copy of the vertex to the sphere radius of the light
1275                                         // (FIXME: would projecting it to the light box be better?)
1276                                         VectorSubtract(vertex, projectorigin, direction);
1277                                         ratio = projectdistance / VectorLength(direction);
1278                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1279                                 }
1280                                 outvertex3f += 6;
1281                                 outvertices += 2;
1282                         }
1283                 }
1284
1285                 // output the sides (facing outward from this triangle)
1286                 if (!side[0])
1287                 {
1288                         remappedelement[0] = vertexremap[element[0]];
1289                         remappedelement[1] = vertexremap[element[1]];
1290                         outelement3i[0] = remappedelement[1];
1291                         outelement3i[1] = remappedelement[0];
1292                         outelement3i[2] = remappedelement[0] + 1;
1293                         outelement3i[3] = remappedelement[1];
1294                         outelement3i[4] = remappedelement[0] + 1;
1295                         outelement3i[5] = remappedelement[1] + 1;
1296
1297                         outelement3i += 6;
1298                         outtriangles += 2;
1299                 }
1300                 if (!side[1])
1301                 {
1302                         remappedelement[1] = vertexremap[element[1]];
1303                         remappedelement[2] = vertexremap[element[2]];
1304                         outelement3i[0] = remappedelement[2];
1305                         outelement3i[1] = remappedelement[1];
1306                         outelement3i[2] = remappedelement[1] + 1;
1307                         outelement3i[3] = remappedelement[2];
1308                         outelement3i[4] = remappedelement[1] + 1;
1309                         outelement3i[5] = remappedelement[2] + 1;
1310
1311                         outelement3i += 6;
1312                         outtriangles += 2;
1313                 }
1314                 if (!side[2])
1315                 {
1316                         remappedelement[0] = vertexremap[element[0]];
1317                         remappedelement[2] = vertexremap[element[2]];
1318                         outelement3i[0] = remappedelement[0];
1319                         outelement3i[1] = remappedelement[2];
1320                         outelement3i[2] = remappedelement[2] + 1;
1321                         outelement3i[3] = remappedelement[0];
1322                         outelement3i[4] = remappedelement[2] + 1;
1323                         outelement3i[5] = remappedelement[0] + 1;
1324
1325                         outelement3i += 6;
1326                         outtriangles += 2;
1327                 }
1328         }
1329         if (outnumvertices)
1330                 *outnumvertices = outvertices;
1331         return outtriangles;
1332 }
1333
1334 void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs)
1335 {
1336         int t, tend;
1337         const int *e;
1338         const float *v[3];
1339         float normal[3];
1340         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1341                 return;
1342         tend = firsttriangle + numtris;
1343         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1344         {
1345                 // surface box entirely inside light box, no box cull
1346                 if (projectdirection)
1347                 {
1348                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1349                         {
1350                                 TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
1351                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1352                                         shadowmarklist[numshadowmark++] = t;
1353                         }
1354                 }
1355                 else
1356                 {
1357                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1358                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
1359                                         shadowmarklist[numshadowmark++] = t;
1360                 }
1361         }
1362         else
1363         {
1364                 // surface box not entirely inside light box, cull each triangle
1365                 if (projectdirection)
1366                 {
1367                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1368                         {
1369                                 v[0] = invertex3f + e[0] * 3;
1370                                 v[1] = invertex3f + e[1] * 3;
1371                                 v[2] = invertex3f + e[2] * 3;
1372                                 TriangleNormal(v[0], v[1], v[2], normal);
1373                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1374                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1375                                         shadowmarklist[numshadowmark++] = t;
1376                         }
1377                 }
1378                 else
1379                 {
1380                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1381                         {
1382                                 v[0] = invertex3f + e[0] * 3;
1383                                 v[1] = invertex3f + e[1] * 3;
1384                                 v[2] = invertex3f + e[2] * 3;
1385                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1386                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1387                                         shadowmarklist[numshadowmark++] = t;
1388                         }
1389                 }
1390         }
1391 }
1392
1393 static qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
1394 {
1395 #if 1
1396         return false;
1397 #else
1398         if (r_shadow_compilingrtlight || !r_shadow_frontsidecasting.integer || !r_shadow_usezpassifpossible.integer)
1399                 return false;
1400         // check if the shadow volume intersects the near plane
1401         //
1402         // a ray between the eye and light origin may intersect the caster,
1403         // indicating that the shadow may touch the eye location, however we must
1404         // test the near plane (a polygon), not merely the eye location, so it is
1405         // easiest to enlarge the caster bounding shape slightly for this.
1406         // TODO
1407         return true;
1408 #endif
1409 }
1410
1411 void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, const vec3_t projectdirection, float projectdistance, int nummarktris, const int *marktris, vec3_t trismins, vec3_t trismaxs)
1412 {
1413         int i, tris, outverts;
1414         if (projectdistance < 0.1)
1415         {
1416                 Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
1417                 return;
1418         }
1419         if (!numverts || !nummarktris)
1420                 return;
1421         // make sure shadowelements is big enough for this volume
1422         if (maxshadowtriangles < nummarktris*8 || maxshadowvertices < numverts*2)
1423                 R_Shadow_ResizeShadowArrays(numverts, nummarktris, 2, 8);
1424
1425         if (maxvertexupdate < numverts)
1426         {
1427                 maxvertexupdate = numverts;
1428                 if (vertexupdate)
1429                         Mem_Free(vertexupdate);
1430                 if (vertexremap)
1431                         Mem_Free(vertexremap);
1432                 vertexupdate = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1433                 vertexremap = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1434                 vertexupdatenum = 0;
1435         }
1436         vertexupdatenum++;
1437         if (vertexupdatenum == 0)
1438         {
1439                 vertexupdatenum = 1;
1440                 memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
1441                 memset(vertexremap, 0, maxvertexupdate * sizeof(int));
1442         }
1443
1444         for (i = 0;i < nummarktris;i++)
1445                 shadowmark[marktris[i]] = shadowmarkcount;
1446
1447         if (r_shadow_compilingrtlight)
1448         {
1449                 // if we're compiling an rtlight, capture the mesh
1450                 //tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1451                 //Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zpass, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1452                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1453                 Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zfail, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1454         }
1455         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1456         {
1457                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1458                 R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
1459                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1460         }
1461         else
1462         {
1463                 // decide which type of shadow to generate and set stencil mode
1464                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1465                 // generate the sides or a solid volume, depending on type
1466                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1467                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1468                 else
1469                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1470                 r_refdef.stats[r_stat_lights_dynamicshadowtriangles] += tris;
1471                 r_refdef.stats[r_stat_lights_shadowtriangles] += tris;
1472                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1473                 {
1474                         // increment stencil if frontface is infront of depthbuffer
1475                         GL_CullFace(r_refdef.view.cullface_front);
1476                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
1477                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1478                         // decrement stencil if backface is infront of depthbuffer
1479                         GL_CullFace(r_refdef.view.cullface_back);
1480                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
1481                 }
1482                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1483                 {
1484                         // decrement stencil if backface is behind depthbuffer
1485                         GL_CullFace(r_refdef.view.cullface_front);
1486                         R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
1487                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1488                         // increment stencil if frontface is behind depthbuffer
1489                         GL_CullFace(r_refdef.view.cullface_back);
1490                         R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
1491                 }
1492                 R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
1493                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1494         }
1495 }
1496
1497 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1498 {
1499         // p1, p2, p3 are in the cubemap's local coordinate system
1500         // bias = border/(size - border)
1501         int mask = 0x3F;
1502
1503         float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1504                   dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1505                   dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1506         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1507                 mask &= (3<<4)
1508                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1509                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1510                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1511         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1512                 mask &= (3<<4)
1513                         | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1514                         | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))                    
1515                         | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1516
1517         dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1518         dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1519         dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1520         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1521                 mask &= (3<<0)
1522                         | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1523                         | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))                    
1524                         | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1525         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1526                 mask &= (3<<0)
1527                         | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1528                         | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1529                         | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1530
1531         dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1532         dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1533         dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1534         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1535                 mask &= (3<<2)
1536                         | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1537                         | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1538                         | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1539         if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1540                 mask &= (3<<2)
1541                         | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1542                         | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1543                         | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1544
1545         return mask;
1546 }
1547
1548 static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1549 {
1550         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1551         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1552         int mask = 0x3F;
1553
1554         VectorSubtract(maxs, mins, radius);
1555         VectorScale(radius, 0.5f, radius);
1556         VectorAdd(mins, radius, center);
1557         Matrix4x4_Transform(worldtolight, center, lightcenter);
1558         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1559         VectorSubtract(lightcenter, lightradius, pmin);
1560         VectorAdd(lightcenter, lightradius, pmax);
1561
1562         dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1563         dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1564         if(ap1 > bias*an1 && ap2 > bias*an2)
1565                 mask &= (3<<4)
1566                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1567                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1568         if(an1 > bias*ap1 && an2 > bias*ap2)
1569                 mask &= (3<<4)
1570                         | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1571                         | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1572
1573         dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1574         dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1575         if(ap1 > bias*an1 && ap2 > bias*an2)
1576                 mask &= (3<<0)
1577                         | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1578                         | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1579         if(an1 > bias*ap1 && an2 > bias*ap2)
1580                 mask &= (3<<0)
1581                         | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1582                         | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1583
1584         dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1585         dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1586         if(ap1 > bias*an1 && ap2 > bias*an2)
1587                 mask &= (3<<2)
1588                         | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1589                         | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1590         if(an1 > bias*ap1 && an2 > bias*ap2)
1591                 mask &= (3<<2)
1592                         | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1593                         | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1594
1595         return mask;
1596 }
1597
1598 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1599
1600 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1601 {
1602         // p is in the cubemap's local coordinate system
1603         // bias = border/(size - border)
1604         float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1605         float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1606         float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1607         int mask = 0x3F;
1608         if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1609         if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1610         if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1611         if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1612         if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1613         if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1614         return mask;
1615 }
1616
1617 static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1618 {
1619         int i;
1620         vec3_t o, p, n;
1621         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1622         float scale = (size - 2*border)/size, len;
1623         float bias = border / (float)(size - border), dp, dn, ap, an;
1624         // check if cone enclosing side would cross frustum plane
1625         scale = 2 / (scale*scale + 2);
1626         Matrix4x4_OriginFromMatrix(&rtlight->matrix_lighttoworld, o);
1627         for (i = 0;i < 5;i++)
1628         {
1629                 if (PlaneDiff(o, &r_refdef.view.frustum[i]) > -0.03125)
1630                         continue;
1631                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1632                 len = scale*VectorLength2(n);
1633                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1634                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1635                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1636         }
1637         if (PlaneDiff(o, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1638         {
1639                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1640                 len = scale*VectorLength2(n);
1641                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1642                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1643                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1644         }
1645         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1646         // check if frustum corners/origin cross plane sides
1647 #if 1
1648         // infinite version, assumes frustum corners merely give direction and extend to infinite distance
1649         Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
1650         dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1651         masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1652         masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1653         dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1654         masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1655         masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1656         dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1657         masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1658         masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1659         for (i = 0;i < 4;i++)
1660         {
1661                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
1662                 VectorSubtract(n, p, n);
1663                 dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
1664                 if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
1665                 if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
1666                 dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
1667                 if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
1668                 if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
1669                 dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
1670                 if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
1671                 if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
1672         }
1673 #else
1674         // finite version, assumes corners are a finite distance from origin dependent on far plane
1675         for (i = 0;i < 5;i++)
1676         {
1677                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1678                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1679                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1680                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1681                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1682                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1683                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1684                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1685                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1686                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1687         }
1688 #endif
1689         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1690 }
1691
1692 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)
1693 {
1694         int t, tend;
1695         const int *e;
1696         const float *v[3];
1697         float normal[3];
1698         vec3_t p[3];
1699         float bias;
1700         int mask, surfacemask = 0;
1701         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1702                 return 0;
1703         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1704         tend = firsttriangle + numtris;
1705         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1706         {
1707                 // surface box entirely inside light box, no box cull
1708                 if (projectdirection)
1709                 {
1710                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1711                         {
1712                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1713                                 TriangleNormal(v[0], v[1], v[2], normal);
1714                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1715                                 {
1716                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1717                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1718                                         surfacemask |= mask;
1719                                         if(totals)
1720                                         {
1721                                                 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;
1722                                                 shadowsides[numshadowsides] = mask;
1723                                                 shadowsideslist[numshadowsides++] = t;
1724                                         }
1725                                 }
1726                         }
1727                 }
1728                 else
1729                 {
1730                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1731                         {
1732                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1733                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1734                                 {
1735                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1736                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1737                                         surfacemask |= mask;
1738                                         if(totals)
1739                                         {
1740                                                 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;
1741                                                 shadowsides[numshadowsides] = mask;
1742                                                 shadowsideslist[numshadowsides++] = t;
1743                                         }
1744                                 }
1745                         }
1746                 }
1747         }
1748         else
1749         {
1750                 // surface box not entirely inside light box, cull each triangle
1751                 if (projectdirection)
1752                 {
1753                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1754                         {
1755                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1756                                 TriangleNormal(v[0], v[1], v[2], normal);
1757                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1758                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1759                                 {
1760                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1761                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1762                                         surfacemask |= mask;
1763                                         if(totals)
1764                                         {
1765                                                 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;
1766                                                 shadowsides[numshadowsides] = mask;
1767                                                 shadowsideslist[numshadowsides++] = t;
1768                                         }
1769                                 }
1770                         }
1771                 }
1772                 else
1773                 {
1774                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1775                         {
1776                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1777                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1778                                  && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1779                                 {
1780                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1781                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1782                                         surfacemask |= mask;
1783                                         if(totals)
1784                                         {
1785                                                 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;
1786                                                 shadowsides[numshadowsides] = mask;
1787                                                 shadowsideslist[numshadowsides++] = t;
1788                                         }
1789                                 }
1790                         }
1791                 }
1792         }
1793         return surfacemask;
1794 }
1795
1796 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)
1797 {
1798         int i, j, outtriangles = 0;
1799         int *outelement3i[6];
1800         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1801                 return;
1802         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1803         // make sure shadowelements is big enough for this mesh
1804         if (maxshadowtriangles < outtriangles)
1805                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1806
1807         // compute the offset and size of the separate index lists for each cubemap side
1808         outtriangles = 0;
1809         for (i = 0;i < 6;i++)
1810         {
1811                 outelement3i[i] = shadowelements + outtriangles * 3;
1812                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1813                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1814                 outtriangles += sidetotals[i];
1815         }
1816
1817         // gather up the (sparse) triangles into separate index lists for each cubemap side
1818         for (i = 0;i < numsidetris;i++)
1819         {
1820                 const int *element = elements + sidetris[i] * 3;
1821                 for (j = 0;j < 6;j++)
1822                 {
1823                         if (sides[i] & (1 << j))
1824                         {
1825                                 outelement3i[j][0] = element[0];
1826                                 outelement3i[j][1] = element[1];
1827                                 outelement3i[j][2] = element[2];
1828                                 outelement3i[j] += 3;
1829                         }
1830                 }
1831         }
1832                         
1833         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1834 }
1835
1836 static void R_Shadow_MakeTextures_MakeCorona(void)
1837 {
1838         float dx, dy;
1839         int x, y, a;
1840         unsigned char pixels[32][32][4];
1841         for (y = 0;y < 32;y++)
1842         {
1843                 dy = (y - 15.5f) * (1.0f / 16.0f);
1844                 for (x = 0;x < 32;x++)
1845                 {
1846                         dx = (x - 15.5f) * (1.0f / 16.0f);
1847                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1848                         a = bound(0, a, 255);
1849                         pixels[y][x][0] = a;
1850                         pixels[y][x][1] = a;
1851                         pixels[y][x][2] = a;
1852                         pixels[y][x][3] = 255;
1853                 }
1854         }
1855         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32, false);
1856 }
1857
1858 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1859 {
1860         float dist = sqrt(x*x+y*y+z*z);
1861         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1862         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1863         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1864 }
1865
1866 static void R_Shadow_MakeTextures(void)
1867 {
1868         int x, y, z;
1869         float intensity, dist;
1870         unsigned int *data;
1871         R_Shadow_FreeShadowMaps();
1872         R_FreeTexturePool(&r_shadow_texturepool);
1873         r_shadow_texturepool = R_AllocTexturePool();
1874         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1875         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1876         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1877         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1878         for (x = 0;x <= ATTENTABLESIZE;x++)
1879         {
1880                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1881                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1882                 r_shadow_attentable[x] = bound(0, intensity, 1);
1883         }
1884         // 1D gradient texture
1885         for (x = 0;x < ATTEN1DSIZE;x++)
1886                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1887         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1888         // 2D circle texture
1889         for (y = 0;y < ATTEN2DSIZE;y++)
1890                 for (x = 0;x < ATTEN2DSIZE;x++)
1891                         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);
1892         r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1893         // 3D sphere texture
1894         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1895         {
1896                 for (z = 0;z < ATTEN3DSIZE;z++)
1897                         for (y = 0;y < ATTEN3DSIZE;y++)
1898                                 for (x = 0;x < ATTEN3DSIZE;x++)
1899                                         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));
1900                 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);
1901         }
1902         else
1903                 r_shadow_attenuation3dtexture = NULL;
1904         Mem_Free(data);
1905
1906         R_Shadow_MakeTextures_MakeCorona();
1907
1908         // Editor light sprites
1909         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1910         "................"
1911         ".3............3."
1912         "..5...2332...5.."
1913         "...7.3....3.7..."
1914         "....7......7...."
1915         "...3.7....7.3..."
1916         "..2...7..7...2.."
1917         "..3..........3.."
1918         "..3..........3.."
1919         "..2...7..7...2.."
1920         "...3.7....7.3..."
1921         "....7......7...."
1922         "...7.3....3.7..."
1923         "..5...2332...5.."
1924         ".3............3."
1925         "................"
1926         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1927         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1928         "................"
1929         "................"
1930         "......1111......"
1931         "....11233211...."
1932         "...1234554321..."
1933         "...1356776531..."
1934         "..124677776421.."
1935         "..135777777531.."
1936         "..135777777531.."
1937         "..124677776421.."
1938         "...1356776531..."
1939         "...1234554321..."
1940         "....11233211...."
1941         "......1111......"
1942         "................"
1943         "................"
1944         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1945         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1946         "................"
1947         "................"
1948         "......1111......"
1949         "....11233211...."
1950         "...1234554321..."
1951         "...1356226531..."
1952         "..12462..26421.."
1953         "..1352....2531.."
1954         "..1352....2531.."
1955         "..12462..26421.."
1956         "...1356226531..."
1957         "...1234554321..."
1958         "....11233211...."
1959         "......1111......"
1960         "................"
1961         "................"
1962         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1963         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1964         "................"
1965         "................"
1966         "......2772......"
1967         "....27755772...."
1968         "..277533335772.."
1969         "..753333333357.."
1970         "..777533335777.."
1971         "..735775577537.."
1972         "..733357753337.."
1973         "..733337733337.."
1974         "..753337733357.."
1975         "..277537735772.."
1976         "....27777772...."
1977         "......2772......"
1978         "................"
1979         "................"
1980         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1981         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1982         "................"
1983         "................"
1984         "......2772......"
1985         "....27722772...."
1986         "..2772....2772.."
1987         "..72........27.."
1988         "..7772....2777.."
1989         "..7.27722772.7.."
1990         "..7...2772...7.."
1991         "..7....77....7.."
1992         "..72...77...27.."
1993         "..2772.77.2772.."
1994         "....27777772...."
1995         "......2772......"
1996         "................"
1997         "................"
1998         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1999         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
2000         "................"
2001         ".777752..257777."
2002         ".742........247."
2003         ".72..........27."
2004         ".7............7."
2005         ".5............5."
2006         ".2............2."
2007         "................"
2008         "................"
2009         ".2............2."
2010         ".5............5."
2011         ".7............7."
2012         ".72..........27."
2013         ".742........247."
2014         ".777752..257777."
2015         "................"
2016         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
2017 }
2018
2019 void R_Shadow_ValidateCvars(void)
2020 {
2021         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
2022                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
2023         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
2024                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
2025         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
2026                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
2027 }
2028
2029 void R_Shadow_RenderMode_Begin(void)
2030 {
2031 #if 0
2032         GLint drawbuffer;
2033         GLint readbuffer;
2034 #endif
2035         R_Shadow_ValidateCvars();
2036
2037         if (!r_shadow_attenuation2dtexture
2038          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
2039          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
2040          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
2041                 R_Shadow_MakeTextures();
2042
2043         CHECKGLERROR
2044         R_Mesh_ResetTextureState();
2045         GL_BlendFunc(GL_ONE, GL_ZERO);
2046         GL_DepthRange(0, 1);
2047         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2048         GL_DepthTest(true);
2049         GL_DepthMask(false);
2050         GL_Color(0, 0, 0, 1);
2051         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2052         
2053         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2054
2055         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
2056         {
2057                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
2058                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
2059         }
2060         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
2061         {
2062                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
2063                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
2064         }
2065         else
2066         {
2067                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
2068                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
2069         }
2070
2071         switch(vid.renderpath)
2072         {
2073         case RENDERPATH_GL20:
2074         case RENDERPATH_D3D9:
2075         case RENDERPATH_D3D10:
2076         case RENDERPATH_D3D11:
2077         case RENDERPATH_SOFT:
2078         case RENDERPATH_GLES2:
2079                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
2080                 break;
2081         case RENDERPATH_GL11:
2082         case RENDERPATH_GL13:
2083         case RENDERPATH_GLES1:
2084                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
2085                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
2086                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
2087                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
2088                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
2089                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
2090                 else
2091                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
2092                 break;
2093         }
2094
2095         CHECKGLERROR
2096 #if 0
2097         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
2098         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
2099         r_shadow_drawbuffer = drawbuffer;
2100         r_shadow_readbuffer = readbuffer;
2101 #endif
2102         r_shadow_cullface_front = r_refdef.view.cullface_front;
2103         r_shadow_cullface_back = r_refdef.view.cullface_back;
2104 }
2105
2106 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
2107 {
2108         rsurface.rtlight = rtlight;
2109 }
2110
2111 void R_Shadow_RenderMode_Reset(void)
2112 {
2113         R_Mesh_ResetTextureState();
2114         R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
2115         R_SetViewport(&r_refdef.view.viewport);
2116         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
2117         GL_DepthRange(0, 1);
2118         GL_DepthTest(true);
2119         GL_DepthMask(false);
2120         GL_DepthFunc(GL_LEQUAL);
2121         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2122         r_refdef.view.cullface_front = r_shadow_cullface_front;
2123         r_refdef.view.cullface_back = r_shadow_cullface_back;
2124         GL_CullFace(r_refdef.view.cullface_back);
2125         GL_Color(1, 1, 1, 1);
2126         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2127         GL_BlendFunc(GL_ONE, GL_ZERO);
2128         R_SetupShader_Generic_NoTexture(false, false);
2129         r_shadow_usingshadowmap2d = false;
2130         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2131 }
2132
2133 void R_Shadow_ClearStencil(void)
2134 {
2135         GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128);
2136         r_refdef.stats[r_stat_lights_clears]++;
2137 }
2138
2139 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
2140 {
2141         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
2142         if (r_shadow_rendermode == mode)
2143                 return;
2144         R_Shadow_RenderMode_Reset();
2145         GL_DepthFunc(GL_LESS);
2146         GL_ColorMask(0, 0, 0, 0);
2147         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2148         GL_CullFace(GL_NONE);
2149         R_SetupShader_DepthOrShadow(false, false, false); // FIXME test if we have a skeletal model?
2150         r_shadow_rendermode = mode;
2151         switch(mode)
2152         {
2153         default:
2154                 break;
2155         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
2156         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
2157                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, GL_ALWAYS, 128, 255);
2158                 break;
2159         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2160         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
2161                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, GL_ALWAYS, 128, 255);
2162                 break;
2163         }
2164 }
2165
2166 static void R_Shadow_MakeVSDCT(void)
2167 {
2168         // maps to a 2x3 texture rectangle with normalized coordinates
2169         // +-
2170         // XX
2171         // YY
2172         // ZZ
2173         // stores abs(dir.xy), offset.xy/2.5
2174         unsigned char data[4*6] =
2175         {
2176                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2177                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2178                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2179                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2180                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2181                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2182         };
2183         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2184 }
2185
2186 static void R_Shadow_MakeShadowMap(int texturesize)
2187 {
2188         switch (r_shadow_shadowmode)
2189         {
2190         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2191                 if (r_shadow_shadowmap2ddepthtexture) return;
2192                 if (r_fb.usedepthtextures)
2193                 {
2194                         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);
2195                         r_shadow_shadowmap2ddepthbuffer = NULL;
2196                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
2197                 }
2198                 else
2199                 {
2200                         r_shadow_shadowmap2ddepthtexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", texturesize, texturesize, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2201                         r_shadow_shadowmap2ddepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "shadowmap", texturesize, texturesize, r_shadow_shadowmapdepthbits >= 24 ? TEXTYPE_DEPTHBUFFER24 : TEXTYPE_DEPTHBUFFER16);
2202                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
2203                 }
2204                 break;
2205         default:
2206                 return;
2207         }
2208 }
2209
2210 void R_Shadow_ClearShadowMapTexture(void)
2211 {
2212         r_viewport_t viewport;
2213         float clearcolor[4];
2214
2215         // if they don't exist, create our textures now
2216         if (!r_shadow_shadowmap2ddepthtexture)
2217                 R_Shadow_MakeShadowMap(r_shadow_shadowmaptexturesize);
2218         if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2219                 R_Shadow_MakeVSDCT();
2220
2221         // we're setting up to render shadowmaps, so change rendermode
2222         r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2223
2224         R_Mesh_ResetTextureState();
2225         R_Shadow_RenderMode_Reset();
2226         if (r_shadow_shadowmap2ddepthbuffer)
2227                 R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
2228         else
2229                 R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
2230         R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
2231         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2232         GL_DepthMask(true);
2233         GL_DepthTest(true);
2234
2235         // we have to set a viewport to clear anything in some renderpaths (D3D)
2236         R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, r_shadow_shadowmaptexturesize, r_shadow_shadowmaptexturesize, 0, 0, 1.0, 1.0, 0.001f, 1.0f, NULL);
2237         R_SetViewport(&viewport);
2238         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2239         if (r_shadow_shadowmap2ddepthbuffer)
2240                 GL_ColorMask(1, 1, 1, 1);
2241         else
2242                 GL_ColorMask(0, 0, 0, 0);
2243         switch (vid.renderpath)
2244         {
2245         case RENDERPATH_GL11:
2246         case RENDERPATH_GL13:
2247         case RENDERPATH_GL20:
2248         case RENDERPATH_SOFT:
2249         case RENDERPATH_GLES1:
2250         case RENDERPATH_GLES2:
2251                 GL_CullFace(r_refdef.view.cullface_back);
2252                 break;
2253         case RENDERPATH_D3D9:
2254         case RENDERPATH_D3D10:
2255         case RENDERPATH_D3D11:
2256                 // we invert the cull mode because we flip the projection matrix
2257                 // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
2258                 GL_CullFace(r_refdef.view.cullface_front);
2259                 break;
2260         }
2261         Vector4Set(clearcolor, 1, 1, 1, 1);
2262         if (r_shadow_shadowmap2ddepthbuffer)
2263                 GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
2264         else
2265                 GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
2266 }
2267
2268 static void R_Shadow_SetShadowmapParametersForLight(qboolean noselfshadowpass)
2269 {
2270         int size = rsurface.rtlight->shadowmapatlassidesize;
2271         float nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2272         float farclip = 1.0f;
2273         float bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2274         r_shadow_lightshadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
2275         r_shadow_lightshadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
2276         r_shadow_lightshadowmap_texturescale[2] = rsurface.rtlight->shadowmapatlasposition[0] + (noselfshadowpass ? size * 2 : 0);
2277         r_shadow_lightshadowmap_texturescale[3] = rsurface.rtlight->shadowmapatlasposition[1];
2278         r_shadow_lightshadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2279         r_shadow_lightshadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2280         r_shadow_lightshadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2281         r_shadow_lightshadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2282         if (r_shadow_shadowmap2ddepthbuffer)
2283         {
2284                 // completely different meaning than in depthtexture approach
2285                 r_shadow_lightshadowmap_parameters[1] = 0;
2286                 r_shadow_lightshadowmap_parameters[3] = -bias;
2287         }
2288 }
2289
2290 static void R_Shadow_RenderMode_ShadowMap(int side, int size, int x, int y)
2291 {
2292         float nearclip, farclip, bias;
2293         r_viewport_t viewport;
2294         int flipped;
2295         float clearcolor[4];
2296
2297         if (r_shadow_rendermode != R_SHADOW_RENDERMODE_SHADOWMAP2D)
2298         {
2299                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2300
2301                 R_Mesh_ResetTextureState();
2302                 R_Shadow_RenderMode_Reset();
2303                 if (r_shadow_shadowmap2ddepthbuffer)
2304                         R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
2305                 else
2306                         R_Mesh_SetRenderTargets(r_shadow_fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
2307                 R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
2308                 GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2309                 GL_DepthMask(true);
2310                 GL_DepthTest(true);
2311         }
2312
2313         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2314         farclip = 1.0f;
2315         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2316
2317         R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL, x, y);
2318         R_SetViewport(&viewport);
2319         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2320         flipped = (side & 1) ^ (side >> 2);
2321         r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2322         r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2323
2324         Vector4Set(clearcolor, 1,1,1,1);
2325         if (r_shadow_shadowmap2ddepthbuffer)
2326                 GL_ColorMask(1,1,1,1);
2327         else
2328                 GL_ColorMask(0,0,0,0);
2329         switch(vid.renderpath)
2330         {
2331         case RENDERPATH_GL11:
2332         case RENDERPATH_GL13:
2333         case RENDERPATH_GL20:
2334         case RENDERPATH_SOFT:
2335         case RENDERPATH_GLES1:
2336         case RENDERPATH_GLES2:
2337                 GL_CullFace(r_refdef.view.cullface_back);
2338                 break;
2339         case RENDERPATH_D3D9:
2340         case RENDERPATH_D3D10:
2341         case RENDERPATH_D3D11:
2342                 // we invert the cull mode because we flip the projection matrix
2343                 // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
2344                 GL_CullFace(r_refdef.view.cullface_front);
2345                 break;
2346         }
2347
2348         // used in R_Q1BSP_DrawShadowMap code to check surfacesides[]
2349         r_shadow_shadowmapside = side;
2350 }
2351
2352 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping, qboolean noselfshadowpass)
2353 {
2354         R_Mesh_ResetTextureState();
2355         if (transparent)
2356         {
2357                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2358                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2359                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2360                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2361         }
2362         if (shadowmapping)
2363                 R_Shadow_SetShadowmapParametersForLight(noselfshadowpass);
2364         R_Shadow_RenderMode_Reset();
2365         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2366         if (!transparent)
2367                 GL_DepthFunc(GL_EQUAL);
2368         // do global setup needed for the chosen lighting mode
2369         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2370                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2371         r_shadow_usingshadowmap2d = shadowmapping;
2372         r_shadow_rendermode = r_shadow_lightingrendermode;
2373         // only draw light where this geometry was already rendered AND the
2374         // stencil is 128 (values other than this mean shadow)
2375         if (stenciltest)
2376                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2377         else
2378                 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2379 }
2380
2381 static const unsigned short bboxelements[36] =
2382 {
2383         5, 1, 3, 5, 3, 7,
2384         6, 2, 0, 6, 0, 4,
2385         7, 3, 2, 7, 2, 6,
2386         4, 0, 1, 4, 1, 5,
2387         4, 5, 7, 4, 7, 6,
2388         1, 0, 2, 1, 2, 3,
2389 };
2390
2391 static const float bboxpoints[8][3] =
2392 {
2393         {-1,-1,-1},
2394         { 1,-1,-1},
2395         {-1, 1,-1},
2396         { 1, 1,-1},
2397         {-1,-1, 1},
2398         { 1,-1, 1},
2399         {-1, 1, 1},
2400         { 1, 1, 1},
2401 };
2402
2403 void R_Shadow_RenderMode_DrawDeferredLight(qboolean shadowmapping)
2404 {
2405         int i;
2406         float vertex3f[8*3];
2407         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
2408 // do global setup needed for the chosen lighting mode
2409         R_Shadow_RenderMode_Reset();
2410         r_shadow_rendermode = r_shadow_lightingrendermode;
2411         R_EntityMatrix(&identitymatrix);
2412         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2413         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2414         if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0)
2415                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
2416         else
2417                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
2418
2419         r_shadow_usingshadowmap2d = shadowmapping;
2420
2421         // render the lighting
2422         R_SetupShader_DeferredLight(rsurface.rtlight);
2423         for (i = 0;i < 8;i++)
2424                 Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
2425         GL_ColorMask(1,1,1,1);
2426         GL_DepthMask(false);
2427         GL_DepthRange(0, 1);
2428         GL_PolygonOffset(0, 0);
2429         GL_DepthTest(true);
2430         GL_DepthFunc(GL_GREATER);
2431         GL_CullFace(r_refdef.view.cullface_back);
2432         R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0);
2433         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
2434 }
2435
2436 #define MAXBOUNCEGRIDSPLATSIZE 7
2437 #define MAXBOUNCEGRIDSPLATSIZE1 (MAXBOUNCEGRIDSPLATSIZE+1)
2438
2439 // these are temporary data per-frame, sorted and performed in a more
2440 // cache-friendly order than the original photons
2441 typedef struct r_shadow_bouncegrid_splatpath_s
2442 {
2443         vec3_t point;
2444         vec3_t step;
2445         vec3_t splatcolor;
2446         vec3_t splatdir;
2447         vec_t splatintensity;
2448         vec_t splatsize_current;
2449         vec_t splatsize_perstep;
2450         int remainingsplats;
2451 }
2452 r_shadow_bouncegrid_splatpath_t;
2453
2454 static void R_Shadow_BounceGrid_AddSplatPath(vec3_t originalstart, vec3_t originalend, vec3_t color, vec_t distancetraveled)
2455 {
2456         int bestaxis;
2457         int numsplats;
2458         float len;
2459         float ilen;
2460         vec3_t start;
2461         vec3_t end;
2462         vec3_t diff;
2463         vec3_t originaldir;
2464         r_shadow_bouncegrid_splatpath_t *path;
2465
2466         // cull paths that fail R_CullBox in dynamic mode
2467         if (!r_shadow_bouncegrid_state.settings.staticmode
2468          && r_shadow_bouncegrid_dynamic_culllightpaths.integer)
2469         {
2470                 vec3_t cullmins, cullmaxs;
2471                 cullmins[0] = min(originalstart[0], originalend[0]) - r_shadow_bouncegrid_state.settings.spacing[0];
2472                 cullmins[1] = min(originalstart[1], originalend[1]) - r_shadow_bouncegrid_state.settings.spacing[1];
2473                 cullmins[2] = min(originalstart[2], originalend[2]) - r_shadow_bouncegrid_state.settings.spacing[2];
2474                 cullmaxs[0] = max(originalstart[0], originalend[0]) + r_shadow_bouncegrid_state.settings.spacing[0];
2475                 cullmaxs[1] = max(originalstart[1], originalend[1]) + r_shadow_bouncegrid_state.settings.spacing[1];
2476                 cullmaxs[2] = max(originalstart[2], originalend[2]) + r_shadow_bouncegrid_state.settings.spacing[2];
2477                 if (R_CullBox(cullmins, cullmaxs))
2478                         return;
2479         }
2480
2481         // if the light path is going upward, reverse it - we always draw down.
2482         if (originalend[2] < originalstart[2])
2483         {
2484                 VectorCopy(originalend, start);
2485                 VectorCopy(originalstart, end);
2486         }
2487         else
2488         {
2489                 VectorCopy(originalstart, start);
2490                 VectorCopy(originalend, end);
2491         }
2492
2493         // transform to texture pixels
2494         start[0] = (start[0] - r_shadow_bouncegrid_state.mins[0]) * r_shadow_bouncegrid_state.ispacing[0];
2495         start[1] = (start[1] - r_shadow_bouncegrid_state.mins[1]) * r_shadow_bouncegrid_state.ispacing[1];
2496         start[2] = (start[2] - r_shadow_bouncegrid_state.mins[2]) * r_shadow_bouncegrid_state.ispacing[2];
2497         end[0] = (end[0] - r_shadow_bouncegrid_state.mins[0]) * r_shadow_bouncegrid_state.ispacing[0];
2498         end[1] = (end[1] - r_shadow_bouncegrid_state.mins[1]) * r_shadow_bouncegrid_state.ispacing[1];
2499         end[2] = (end[2] - r_shadow_bouncegrid_state.mins[2]) * r_shadow_bouncegrid_state.ispacing[2];
2500
2501         // check if we need to grow the splatpaths array
2502         if (r_shadow_bouncegrid_state.maxsplatpaths <= r_shadow_bouncegrid_state.numsplatpaths)
2503         {
2504                 // double the limit, this will persist from frame to frame so we don't
2505                 // make the same mistake each time
2506                 r_shadow_bouncegrid_state.maxsplatpaths *= 2;
2507                 if (r_shadow_bouncegrid_state.maxsplatpaths < 16384)
2508                         r_shadow_bouncegrid_state.maxsplatpaths = 16384;
2509                 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);
2510         }
2511
2512         // divide a series of splats along the length using the maximum axis
2513         VectorSubtract(end, start, diff);
2514         // pick the best axis to trace along
2515         bestaxis = 0;
2516         if (diff[1]*diff[1] > diff[bestaxis]*diff[bestaxis])
2517                 bestaxis = 1;
2518         if (diff[2]*diff[2] > diff[bestaxis]*diff[bestaxis])
2519                 bestaxis = 2;
2520         len = fabs(diff[bestaxis]);
2521         ilen = 1.0f / len;
2522         numsplats = (int)(floor(len + 0.5f));
2523         // sanity limits
2524         numsplats = bound(0, numsplats, 1024);
2525
2526         VectorSubtract(originalstart, originalend, originaldir);
2527         VectorNormalize(originaldir);
2528
2529         path = r_shadow_bouncegrid_state.splatpaths + r_shadow_bouncegrid_state.numsplatpaths++;
2530         VectorCopy(start, path->point);
2531         VectorScale(diff, ilen, path->step);
2532         VectorCopy(color, path->splatcolor);
2533         VectorCopy(originaldir, path->splatdir);
2534         path->splatsize_current = r_shadow_bouncegrid_state.settings.lightpathsize_initial + r_shadow_bouncegrid_state.settings.lightpathsize_conespread * distancetraveled * r_shadow_bouncegrid_state.ispacing[0];
2535         path->splatsize_perstep = r_shadow_bouncegrid_state.settings.lightpathsize_conespread;
2536         path->splatintensity = VectorLength(color);
2537         path->remainingsplats = numsplats;
2538 }
2539
2540 static qboolean R_Shadow_BounceGrid_CheckEnable(int flag)
2541 {
2542         qboolean enable = r_shadow_bouncegrid_state.capable && r_shadow_bouncegrid.integer != 0 && r_refdef.scene.worldmodel;
2543         int lightindex;
2544         int range;
2545         dlight_t *light;
2546         rtlight_t *rtlight;
2547         vec3_t lightcolor;
2548
2549         // see if there are really any lights to render...
2550         if (enable && r_shadow_bouncegrid_static.integer)
2551         {
2552                 enable = false;
2553                 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
2554                 for (lightindex = 0;lightindex < range;lightindex++)
2555                 {
2556                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2557                         if (!light || !(light->flags & flag))
2558                                 continue;
2559                         rtlight = &light->rtlight;
2560                         // when static, we skip styled lights because they tend to change...
2561                         if (rtlight->style > 0)
2562                                 continue;
2563                         VectorScale(rtlight->color, (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale), lightcolor);
2564                         if (!VectorLength2(lightcolor))
2565                                 continue;
2566                         enable = true;
2567                         break;
2568                 }
2569         }
2570
2571         return enable;
2572 }
2573
2574 static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t *settings)
2575 {
2576         qboolean s = r_shadow_bouncegrid_static.integer != 0;
2577         float spacing = bound(1.0f, s ? r_shadow_bouncegrid_static_spacing.value : r_shadow_bouncegrid_dynamic_spacing.value, 1024.0f);
2578         float quality = bound(0.0001f, (s ? r_shadow_bouncegrid_static_quality.value : r_shadow_bouncegrid_dynamic_quality.value), 1024.0f);
2579         float bounceminimumintensity = s ? r_shadow_bouncegrid_static_bounceminimumintensity.value : r_shadow_bouncegrid_dynamic_bounceminimumintensity.value;
2580
2581         // prevent any garbage in alignment padded areas as we'll be using memcmp
2582         memset(settings, 0, sizeof(*settings));
2583
2584         // build up a complete collection of the desired settings, so that memcmp can be used to compare parameters
2585         settings->staticmode                    = s;
2586         settings->blur                          = r_shadow_bouncegrid_blur.integer != 0;
2587         settings->floatcolors                   = bound(0, r_shadow_bouncegrid_floatcolors.integer, 2);
2588         settings->lightpathsize_initial         = bound(0.0f, r_shadow_bouncegrid_lightpathsize_initial.value, 1024.0f);
2589         settings->lightpathsize_conespread      = bound(0.0f, r_shadow_bouncegrid_lightpathsize_conespread.value, 1024.0f);
2590         settings->bounceanglediffuse            = r_shadow_bouncegrid_bounceanglediffuse.integer != 0;
2591         settings->directionalshading            = (s ? r_shadow_bouncegrid_static_directionalshading.integer != 0 : r_shadow_bouncegrid_dynamic_directionalshading.integer != 0) && r_shadow_bouncegrid_state.allowdirectionalshading;
2592         settings->dlightparticlemultiplier      = s ? 0 : r_shadow_bouncegrid_dynamic_dlightparticlemultiplier.value;
2593         settings->hitmodels                     = s ? false : r_shadow_bouncegrid_dynamic_hitmodels.integer != 0;
2594         settings->includedirectlighting         = r_shadow_bouncegrid_includedirectlighting.integer != 0 || r_shadow_bouncegrid.integer == 2;
2595         settings->lightradiusscale              = (s ? r_shadow_bouncegrid_static_lightradiusscale.value : r_shadow_bouncegrid_dynamic_lightradiusscale.value);
2596         settings->maxbounce                     = (s ? r_shadow_bouncegrid_static_maxbounce.integer : r_shadow_bouncegrid_dynamic_maxbounce.integer);
2597         settings->particlebounceintensity       = r_shadow_bouncegrid_particlebounceintensity.value;
2598         settings->particleintensity             = r_shadow_bouncegrid_particleintensity.value * (settings->directionalshading ? 4.0f : 1.0f) * 16384 / (spacing * spacing) / 262144.0f;
2599         settings->maxphotons                    = s ? r_shadow_bouncegrid_static_maxphotons.integer : r_shadow_bouncegrid_dynamic_maxphotons.integer;
2600         settings->energyperphoton               = spacing * spacing / quality;
2601         settings->spacing[0]                    = spacing;
2602         settings->spacing[1]                    = spacing;
2603         settings->spacing[2]                    = spacing;
2604         settings->rng_type                      = r_shadow_bouncegrid_rng_type.integer;
2605         settings->rng_seed                      = r_shadow_bouncegrid_rng_seed.integer;
2606         settings->bounceminimumintensity2       = bounceminimumintensity * bounceminimumintensity;
2607         settings->bounceminimumintensity2       = bounceminimumintensity * bounceminimumintensity;
2608         settings->normalizevectors              = r_shadow_bouncegrid_normalizevectors.integer != 0;
2609
2610         // bound the values for sanity
2611         settings->maxphotons = bound(1, settings->maxphotons, 25000000);
2612         settings->lightradiusscale = bound(0.0001f, settings->lightradiusscale, 1024.0f);
2613         settings->maxbounce = bound(0, settings->maxbounce, 16);
2614         settings->spacing[0] = bound(1, settings->spacing[0], 512);
2615         settings->spacing[1] = bound(1, settings->spacing[1], 512);
2616         settings->spacing[2] = bound(1, settings->spacing[2], 512);
2617 }
2618
2619 static void R_Shadow_BounceGrid_UpdateSpacing(void)
2620 {
2621         float m[16];
2622         int c[4];
2623         int resolution[3];
2624         int numpixels;
2625         vec3_t ispacing;
2626         vec3_t maxs;
2627         vec3_t mins;
2628         vec3_t size;
2629         vec3_t spacing;
2630         r_shadow_bouncegrid_settings_t *settings = &r_shadow_bouncegrid_state.settings;
2631
2632         // get the spacing values
2633         spacing[0] = settings->spacing[0];
2634         spacing[1] = settings->spacing[1];
2635         spacing[2] = settings->spacing[2];
2636         ispacing[0] = 1.0f / spacing[0];
2637         ispacing[1] = 1.0f / spacing[1];
2638         ispacing[2] = 1.0f / spacing[2];
2639
2640         // calculate texture size enclosing entire world bounds at the spacing
2641         if (r_refdef.scene.worldmodel)
2642         {
2643                 int lightindex;
2644                 int range;
2645                 qboolean bounds_set = false;
2646                 dlight_t *light;
2647                 rtlight_t *rtlight;
2648
2649                 // calculate bounds enclosing world lights as they should be noticably tighter 
2650                 // than the world bounds on maps with unlit monster containers (see e1m7 etc)
2651                 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
2652                 for (lightindex = 0;lightindex < range;lightindex++)
2653                 {
2654                         const vec_t *rtlmins, *rtlmaxs;
2655
2656                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2657                         if (!light)
2658                                 continue;
2659
2660                         rtlight = &light->rtlight;
2661                         rtlmins = rtlight->cullmins;
2662                         rtlmaxs = rtlight->cullmaxs;
2663
2664                         if (!bounds_set)
2665                         {
2666                                 VectorCopy(rtlmins, mins);
2667                                 VectorCopy(rtlmaxs, maxs);
2668                                 bounds_set = true;
2669                         }
2670                         else
2671                         {
2672                                 mins[0] = min(mins[0], rtlmins[0]);
2673                                 mins[1] = min(mins[1], rtlmins[1]);
2674                                 mins[2] = min(mins[2], rtlmins[2]);
2675                                 maxs[0] = max(maxs[0], rtlmaxs[0]);
2676                                 maxs[1] = max(maxs[1], rtlmaxs[1]);
2677                                 maxs[2] = max(maxs[2], rtlmaxs[2]);
2678                         }
2679                 }
2680
2681                 // limit to no larger than the world bounds
2682                 mins[0] = max(mins[0], r_refdef.scene.worldmodel->normalmins[0]);
2683                 mins[1] = max(mins[1], r_refdef.scene.worldmodel->normalmins[1]);
2684                 mins[2] = max(mins[2], r_refdef.scene.worldmodel->normalmins[2]);
2685                 maxs[0] = min(maxs[0], r_refdef.scene.worldmodel->normalmaxs[0]);
2686                 maxs[1] = min(maxs[1], r_refdef.scene.worldmodel->normalmaxs[1]);
2687                 maxs[2] = min(maxs[2], r_refdef.scene.worldmodel->normalmaxs[2]);
2688
2689                 VectorMA(mins, -2.0f, spacing, mins);
2690                 VectorMA(maxs, 2.0f, spacing, maxs);
2691         }
2692         else
2693         {
2694                 VectorSet(mins, -1048576.0f, -1048576.0f, -1048576.0f);
2695                 VectorSet(maxs,  1048576.0f,  1048576.0f,  1048576.0f);
2696         }
2697         VectorSubtract(maxs, mins, size);
2698         // now we can calculate the resolution we want
2699         c[0] = (int)floor(size[0] / spacing[0] + 0.5f);
2700         c[1] = (int)floor(size[1] / spacing[1] + 0.5f);
2701         c[2] = (int)floor(size[2] / spacing[2] + 0.5f);
2702         // figure out the exact texture size (honoring power of 2 if required)
2703         c[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
2704         c[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
2705         c[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
2706         if (vid.support.arb_texture_non_power_of_two)
2707         {
2708                 resolution[0] = c[0];
2709                 resolution[1] = c[1];
2710                 resolution[2] = c[2];
2711         }
2712         else
2713         {
2714                 for (resolution[0] = 4;resolution[0] < c[0];resolution[0]*=2) ;
2715                 for (resolution[1] = 4;resolution[1] < c[1];resolution[1]*=2) ;
2716                 for (resolution[2] = 4;resolution[2] < c[2];resolution[2]*=2) ;
2717         }
2718         size[0] = spacing[0] * resolution[0];
2719         size[1] = spacing[1] * resolution[1];
2720         size[2] = spacing[2] * resolution[2];
2721
2722         // if dynamic we may or may not want to use the world bounds
2723         // if the dynamic size is smaller than the world bounds, use it instead
2724         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]))
2725         {
2726                 // we know the resolution we want
2727                 c[0] = r_shadow_bouncegrid_dynamic_x.integer;
2728                 c[1] = r_shadow_bouncegrid_dynamic_y.integer;
2729                 c[2] = r_shadow_bouncegrid_dynamic_z.integer;
2730                 // now we can calculate the texture size (power of 2 if required)
2731                 c[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
2732                 c[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
2733                 c[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
2734                 if (vid.support.arb_texture_non_power_of_two)
2735                 {
2736                         resolution[0] = c[0];
2737                         resolution[1] = c[1];
2738                         resolution[2] = c[2];
2739                 }
2740                 else
2741                 {
2742                         for (resolution[0] = 4;resolution[0] < c[0];resolution[0]*=2) ;
2743                         for (resolution[1] = 4;resolution[1] < c[1];resolution[1]*=2) ;
2744                         for (resolution[2] = 4;resolution[2] < c[2];resolution[2]*=2) ;
2745                 }
2746                 size[0] = spacing[0] * resolution[0];
2747                 size[1] = spacing[1] * resolution[1];
2748                 size[2] = spacing[2] * resolution[2];
2749                 // center the rendering on the view
2750                 mins[0] = floor(r_refdef.view.origin[0] * ispacing[0] + 0.5f) * spacing[0] - 0.5f * size[0];
2751                 mins[1] = floor(r_refdef.view.origin[1] * ispacing[1] + 0.5f) * spacing[1] - 0.5f * size[1];
2752                 mins[2] = floor(r_refdef.view.origin[2] * ispacing[2] + 0.5f) * spacing[2] - 0.5f * size[2];
2753         }
2754
2755         // recalculate the maxs in case the resolution was not satisfactory
2756         VectorAdd(mins, size, maxs);
2757
2758         // check if this changed the texture size
2759         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);
2760         r_shadow_bouncegrid_state.directional = r_shadow_bouncegrid_state.settings.directionalshading;
2761         VectorCopy(mins, r_shadow_bouncegrid_state.mins);
2762         VectorCopy(maxs, r_shadow_bouncegrid_state.maxs);
2763         VectorCopy(size, r_shadow_bouncegrid_state.size);
2764         VectorCopy(spacing, r_shadow_bouncegrid_state.spacing);
2765         VectorCopy(ispacing, r_shadow_bouncegrid_state.ispacing);
2766         VectorCopy(resolution, r_shadow_bouncegrid_state.resolution);
2767
2768         // reallocate pixels for this update if needed...
2769         r_shadow_bouncegrid_state.pixelbands = settings->directionalshading ? 8 : 1;
2770         r_shadow_bouncegrid_state.pixelsperband = resolution[0]*resolution[1]*resolution[2];
2771         r_shadow_bouncegrid_state.bytesperband = r_shadow_bouncegrid_state.pixelsperband*4;
2772         numpixels = r_shadow_bouncegrid_state.pixelsperband*r_shadow_bouncegrid_state.pixelbands;
2773         if (r_shadow_bouncegrid_state.numpixels != numpixels)
2774         {
2775                 if (r_shadow_bouncegrid_state.texture) R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL;
2776                 r_shadow_bouncegrid_state.highpixels = NULL;
2777                 if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
2778                 if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
2779                 if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
2780                 if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
2781                 if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
2782                 r_shadow_bouncegrid_state.maxsplatpaths = 0;
2783                 r_shadow_bouncegrid_state.numpixels = numpixels;
2784         }
2785
2786         // update the bouncegrid matrix to put it in the world properly
2787         memset(m, 0, sizeof(m));
2788         m[0] = 1.0f / r_shadow_bouncegrid_state.size[0];
2789         m[3] = -r_shadow_bouncegrid_state.mins[0] * m[0];
2790         m[5] = 1.0f / r_shadow_bouncegrid_state.size[1];
2791         m[7] = -r_shadow_bouncegrid_state.mins[1] * m[5];
2792         m[10] = 1.0f / r_shadow_bouncegrid_state.size[2];
2793         m[11] = -r_shadow_bouncegrid_state.mins[2] * m[10];
2794         m[15] = 1.0f;
2795         Matrix4x4_FromArrayFloatD3D(&r_shadow_bouncegrid_state.matrix, m);
2796 }
2797
2798 // enumerate world rtlights and sum the overall amount of light in the world,
2799 // from that we can calculate a scaling factor to fairly distribute photons
2800 // to all the lights
2801 //
2802 // this modifies rtlight->photoncolor and rtlight->photons
2803 static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *settings, unsigned int range, unsigned int range1, unsigned int range2, int flag)
2804 {
2805         float normalphotonscaling;
2806         float photonscaling;
2807         float photonintensity;
2808         float photoncount = 0.0f;
2809         float lightintensity;
2810         float radius;
2811         float s;
2812         float w;
2813         vec3_t cullmins;
2814         vec3_t cullmaxs;
2815         unsigned int lightindex;
2816         dlight_t *light;
2817         rtlight_t *rtlight;
2818         normalphotonscaling = 1.0f / max(0.0001f, settings->energyperphoton);
2819         for (lightindex = 0;lightindex < range2;lightindex++)
2820         {
2821                 if (lightindex < range)
2822                 {
2823                         light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2824                         if (!light)
2825                                 continue;
2826                         rtlight = &light->rtlight;
2827                         VectorClear(rtlight->bouncegrid_photoncolor);
2828                         rtlight->bouncegrid_photons = 0;
2829                         rtlight->bouncegrid_hits = 0;
2830                         rtlight->bouncegrid_traces = 0;
2831                         rtlight->bouncegrid_effectiveradius = 0;
2832                         if (!(light->flags & flag))
2833                                 continue;
2834                         if (settings->staticmode)
2835                         {
2836                                 // when static, we skip styled lights because they tend to change...
2837                                 if (rtlight->style > 0 && r_shadow_bouncegrid.integer != 2)
2838                                         continue;
2839                         }
2840                         else if (r_shadow_debuglight.integer >= 0 && (int)lightindex != r_shadow_debuglight.integer)
2841                                 continue;
2842                 }
2843                 else
2844                 {
2845                         rtlight = r_refdef.scene.lights[lightindex - range];
2846                         VectorClear(rtlight->bouncegrid_photoncolor);
2847                         rtlight->bouncegrid_photons = 0;
2848                         rtlight->bouncegrid_hits = 0;
2849                         rtlight->bouncegrid_traces = 0;
2850                         rtlight->bouncegrid_effectiveradius = 0;
2851                 }
2852                 // draw only visible lights (major speedup)
2853                 radius = rtlight->radius * settings->lightradiusscale;
2854                 cullmins[0] = rtlight->shadoworigin[0] - radius;
2855                 cullmins[1] = rtlight->shadoworigin[1] - radius;
2856                 cullmins[2] = rtlight->shadoworigin[2] - radius;
2857                 cullmaxs[0] = rtlight->shadoworigin[0] + radius;
2858                 cullmaxs[1] = rtlight->shadoworigin[1] + radius;
2859                 cullmaxs[2] = rtlight->shadoworigin[2] + radius;
2860                 w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2861                 if (!settings->staticmode)
2862                 {
2863                         // skip if the expanded light box does not touch any visible leafs
2864                         if (r_refdef.scene.worldmodel
2865                                 && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs
2866                                 && !r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, cullmins, cullmaxs))
2867                                 continue;
2868                         // skip if the expanded light box is not visible to traceline
2869                         // note that PrepareLight already did this check but for a smaller box, so we
2870                         // end up casting more traces per frame per light when using bouncegrid, which
2871                         // is probably fine (and they use the same timer)
2872                         if (r_shadow_culllights_trace.integer)
2873                         {
2874                                 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_refdef.view.origin, rtlight->cullmins, rtlight->cullmaxs))
2875                                         rtlight->trace_timer = realtime;
2876                                 if (realtime - rtlight->trace_timer > r_shadow_culllights_trace_delay.value)
2877                                         return;
2878                         }
2879                         // skip if expanded light box is offscreen
2880                         if (R_CullBox(cullmins, cullmaxs))
2881                                 continue;
2882                         // skip if overall light intensity is zero
2883                         if (w * VectorLength2(rtlight->color) == 0.0f)
2884                                 continue;
2885                 }
2886                 // a light that does not emit any light before style is applied, can be
2887                 // skipped entirely (it may just be a corona)
2888                 if (rtlight->radius == 0.0f || VectorLength2(rtlight->color) == 0.0f)
2889                         continue;
2890                 w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
2891                 VectorScale(rtlight->color, w, rtlight->bouncegrid_photoncolor);
2892                 // skip lights that will emit no photons
2893                 if (!VectorLength2(rtlight->bouncegrid_photoncolor))
2894                         continue;
2895                 // shoot particles from this light
2896                 // use a calculation for the number of particles that will not
2897                 // vary with lightstyle, otherwise we get randomized particle
2898                 // distribution, the seeded random is only consistent for a
2899                 // consistent number of particles on this light...
2900                 s = rtlight->radius;
2901                 lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2902                 if (lightindex >= range)
2903                         lightintensity *= settings->dlightparticlemultiplier;
2904                 rtlight->bouncegrid_photons = lightintensity * s * s * normalphotonscaling;
2905                 photoncount += rtlight->bouncegrid_photons;
2906                 VectorScale(rtlight->bouncegrid_photoncolor, settings->particleintensity * settings->energyperphoton, rtlight->bouncegrid_photoncolor);
2907                 // if the lightstyle happens to be off right now, we can skip actually
2908                 // firing the photons, but we did have to count them in the total.
2909                 //if (VectorLength2(rtlight->photoncolor) == 0.0f)
2910                 //      rtlight->bouncegrid_photons = 0;
2911         }
2912         // the user provided an energyperphoton value which we try to use
2913         // if that results in too many photons to shoot this frame, then we cap it
2914         // which causes photons to appear/disappear from frame to frame, so we don't
2915         // like doing that in the typical case
2916         photonscaling = 1.0f;
2917         photonintensity = 1.0f;
2918         if (photoncount > settings->maxphotons)
2919         {
2920                 photonscaling = settings->maxphotons / photoncount;
2921                 photonintensity = 1.0f / photonscaling;
2922         }
2923
2924         // modify the lights to reflect our computed scaling
2925         for (lightindex = 0; lightindex < range2; lightindex++)
2926         {
2927                 if (lightindex < range)
2928                 {
2929                         light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2930                         if (!light)
2931                                 continue;
2932                         rtlight = &light->rtlight;
2933                 }
2934                 else
2935                         rtlight = r_refdef.scene.lights[lightindex - range];
2936                 rtlight->bouncegrid_photons *= photonscaling;
2937                 VectorScale(rtlight->bouncegrid_photoncolor, photonintensity, rtlight->bouncegrid_photoncolor);
2938         }
2939 }
2940
2941 static int R_Shadow_BounceGrid_SplatPathCompare(const void *pa, const void *pb)
2942 {
2943         r_shadow_bouncegrid_splatpath_t *a = (r_shadow_bouncegrid_splatpath_t *)pa;
2944         r_shadow_bouncegrid_splatpath_t *b = (r_shadow_bouncegrid_splatpath_t *)pb;
2945         // we only really care about sorting by Z
2946         if (a->point[2] < b->point[2])
2947                 return -1;
2948         if (a->point[2] > b->point[2])
2949                 return 1;
2950         return 0;
2951 }
2952
2953 static void R_Shadow_BounceGrid_ClearPixels(void)
2954 {
2955         // clear the highpixels array we'll be accumulating into
2956         if (r_shadow_bouncegrid_state.blurpixels[0] == NULL)
2957                 r_shadow_bouncegrid_state.blurpixels[0] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2958         if (r_shadow_bouncegrid_state.settings.blur && r_shadow_bouncegrid_state.blurpixels[1] == NULL)
2959                 r_shadow_bouncegrid_state.blurpixels[1] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2960         r_shadow_bouncegrid_state.highpixels_index = 0;
2961         r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
2962         memset(r_shadow_bouncegrid_state.highpixels, 0, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
2963 }
2964
2965 static void R_Shadow_BounceGrid_PerformSplats(void)
2966 {
2967         r_shadow_bouncegrid_splatpath_t *splatpaths = r_shadow_bouncegrid_state.splatpaths;
2968         r_shadow_bouncegrid_splatpath_t *splatpath;
2969         float *highpixels = r_shadow_bouncegrid_state.highpixels;
2970         int numsplatpaths = r_shadow_bouncegrid_state.numsplatpaths;
2971         int splatindex;
2972         vec3_t steppos;
2973         vec3_t stepdelta;
2974         vec3_t dir;
2975         vec_t lightpathsize_current;
2976         vec_t lightpathsize_perstep;
2977         float splatcolor[32];
2978         int resolution[3];
2979         int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
2980         int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2981         int numsteps;
2982         int step;
2983
2984         // hush warnings about uninitialized data - pixelbands doesn't change but...
2985         memset(splatcolor, 0, sizeof(splatcolor));
2986
2987         // we use this a lot, so get a local copy
2988         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
2989
2990         // sort the splats before we execute them, to reduce cache misses
2991         if (r_shadow_bouncegrid_sortlightpaths.integer)
2992                 qsort(splatpaths, numsplatpaths, sizeof(*splatpaths), R_Shadow_BounceGrid_SplatPathCompare);
2993
2994         splatpath = splatpaths;
2995         for (splatindex = 0;splatindex < numsplatpaths;splatindex++, splatpath++)
2996         {
2997                 // calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
2998                 // accumulate average shotcolor
2999                 VectorCopy(splatpath->splatdir, dir);
3000                 splatcolor[ 0] = splatpath->splatcolor[0];
3001                 splatcolor[ 1] = splatpath->splatcolor[1];
3002                 splatcolor[ 2] = splatpath->splatcolor[2];
3003                 splatcolor[ 3] = 0.0f;
3004                 if (pixelbands > 1)
3005                 {
3006                         // store bentnormal in case the shader has a use for it,
3007                         // bentnormal is an intensity-weighted average of the directions,
3008                         // and will be normalized on conversion to texture pixels.
3009                         splatcolor[ 4] = dir[0] * splatpath->splatintensity;
3010                         splatcolor[ 5] = dir[1] * splatpath->splatintensity;
3011                         splatcolor[ 6] = dir[2] * splatpath->splatintensity;
3012                         splatcolor[ 7] = splatpath->splatintensity;
3013                         // for each color component (R, G, B) calculate the amount that a
3014                         // direction contributes
3015                         splatcolor[ 8] = splatcolor[0] * max(0.0f, dir[0]);
3016                         splatcolor[ 9] = splatcolor[0] * max(0.0f, dir[1]);
3017                         splatcolor[10] = splatcolor[0] * max(0.0f, dir[2]);
3018                         splatcolor[11] = 0.0f;
3019                         splatcolor[12] = splatcolor[1] * max(0.0f, dir[0]);
3020                         splatcolor[13] = splatcolor[1] * max(0.0f, dir[1]);
3021                         splatcolor[14] = splatcolor[1] * max(0.0f, dir[2]);
3022                         splatcolor[15] = 0.0f;
3023                         splatcolor[16] = splatcolor[2] * max(0.0f, dir[0]);
3024                         splatcolor[17] = splatcolor[2] * max(0.0f, dir[1]);
3025                         splatcolor[18] = splatcolor[2] * max(0.0f, dir[2]);
3026                         splatcolor[19] = 0.0f;
3027                         // and do the same for negative directions
3028                         splatcolor[20] = splatcolor[0] * max(0.0f, -dir[0]);
3029                         splatcolor[21] = splatcolor[0] * max(0.0f, -dir[1]);
3030                         splatcolor[22] = splatcolor[0] * max(0.0f, -dir[2]);
3031                         splatcolor[23] = 0.0f;
3032                         splatcolor[24] = splatcolor[1] * max(0.0f, -dir[0]);
3033                         splatcolor[25] = splatcolor[1] * max(0.0f, -dir[1]);
3034                         splatcolor[26] = splatcolor[1] * max(0.0f, -dir[2]);
3035                         splatcolor[27] = 0.0f;
3036                         splatcolor[28] = splatcolor[2] * max(0.0f, -dir[0]);
3037                         splatcolor[29] = splatcolor[2] * max(0.0f, -dir[1]);
3038                         splatcolor[30] = splatcolor[2] * max(0.0f, -dir[2]);
3039                         splatcolor[31] = 0.0f;
3040                 }
3041                 // calculate the number of steps we need to traverse this distance
3042                 VectorCopy(splatpath->point, steppos);
3043                 VectorCopy(splatpath->step, stepdelta);
3044                 numsteps = splatpath->remainingsplats;
3045                 lightpathsize_current = splatpath->splatsize_current + 1.0f; // add 1.0 for the gradient fade around the sphere
3046                 lightpathsize_perstep = splatpath->splatsize_perstep;
3047                 for (step = 0;step < numsteps;step++)
3048                 {
3049                         // the middle row/column/layer of each splat are full intensity
3050                         float splatmins[3];
3051                         float splatmaxs[3];
3052                         if (lightpathsize_current > MAXBOUNCEGRIDSPLATSIZE)
3053                                 lightpathsize_current = MAXBOUNCEGRIDSPLATSIZE;
3054                         splatmins[0] = max(1.0f, steppos[0] - lightpathsize_current * 0.5f);
3055                         splatmins[1] = max(1.0f, steppos[1] - lightpathsize_current * 0.5f);
3056                         splatmins[2] = max(1.0f, steppos[2] - lightpathsize_current * 0.5f);
3057                         splatmaxs[0] = min(steppos[0] + lightpathsize_current * 0.5f, resolution[0] - 1.0f);
3058                         splatmaxs[1] = min(steppos[1] + lightpathsize_current * 0.5f, resolution[1] - 1.0f);
3059                         splatmaxs[2] = min(steppos[2] + lightpathsize_current * 0.5f, resolution[2] - 1.0f);
3060                         if (splatmaxs[0] > splatmins[0] && splatmaxs[1] > splatmins[1] && splatmaxs[2] > splatmins[2])
3061                         {
3062                                 // it is within bounds...  do the real work now
3063                                 int xi, yi, zi, band, row;
3064                                 float pixelpos[3];
3065                                 float w;
3066                                 float *p;
3067                                 float colorscale = 1.0f / lightpathsize_current;
3068                                 r_refdef.stats[r_stat_bouncegrid_splats]++;
3069                                 // accumulate light onto the pixels
3070                                 for (zi = (int)floor(splatmins[2]);zi < splatmaxs[2];zi++)
3071                                 {
3072                                         pixelpos[2] = zi + 0.5f;
3073                                         for (yi = (int)floor(splatmins[1]); yi < splatmaxs[1]; yi++)
3074                                         {
3075                                                 pixelpos[1] = yi + 0.5f;
3076                                                 row = (zi*resolution[1] + yi)*resolution[0];
3077                                                 for (xi = (int)floor(splatmins[0]); xi < splatmaxs[0]; xi++)
3078                                                 {
3079                                                         pixelpos[0] = xi + 0.5f;
3080                                                         // simple radial antialiased sphere - linear gradient fade over 1 pixel from the edge
3081                                                         w = lightpathsize_current - VectorDistance(pixelpos, steppos);
3082                                                         if (w > 0.0f)
3083                                                         {
3084                                                                 if (w > 1.0f)
3085                                                                         w = 1.0f;
3086                                                                 w *= colorscale;
3087                                                                 p = highpixels + 4 * (row + xi);
3088                                                                 for (band = 0; band < pixelbands; band++, p += pixelsperband * 4)
3089                                                                 {
3090                                                                         // add to the pixel color
3091                                                                         p[0] += splatcolor[band * 4 + 0] * w;
3092                                                                         p[1] += splatcolor[band * 4 + 1] * w;
3093                                                                         p[2] += splatcolor[band * 4 + 2] * w;
3094                                                                         p[3] += splatcolor[band * 4 + 3] * w;
3095                                                                 }
3096                                                         }
3097                                                 }
3098                                         }
3099                                 }
3100                         }
3101                         VectorAdd(steppos, stepdelta, steppos);
3102                         lightpathsize_current += lightpathsize_perstep;
3103                 }
3104         }
3105 }
3106
3107 static void R_Shadow_BounceGrid_BlurPixelsInDirection(const float *inpixels, float *outpixels, int off)
3108 {
3109         const float *inpixel;
3110         float *outpixel;
3111         int pixelbands = r_shadow_bouncegrid_state.pixelbands;
3112         int pixelband;
3113         unsigned int index;
3114         unsigned int x, y, z;
3115         unsigned int resolution[3];
3116         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
3117         for (pixelband = 0;pixelband < pixelbands;pixelband++)
3118         {
3119                 for (z = 1;z < resolution[2]-1;z++)
3120                 {
3121                         for (y = 1;y < resolution[1]-1;y++)
3122                         {
3123                                 x = 1;
3124                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
3125                                 inpixel = inpixels + 4*index;
3126                                 outpixel = outpixels + 4*index;
3127                                 for (;x < resolution[0]-1;x++, inpixel += 4, outpixel += 4)
3128                                 {
3129                                         outpixel[0] = (inpixel[0] + inpixel[  off] + inpixel[0-off]) * (1.0f / 3.0);
3130                                         outpixel[1] = (inpixel[1] + inpixel[1+off] + inpixel[1-off]) * (1.0f / 3.0);
3131                                         outpixel[2] = (inpixel[2] + inpixel[2+off] + inpixel[2-off]) * (1.0f / 3.0);
3132                                         outpixel[3] = (inpixel[3] + inpixel[3+off] + inpixel[3-off]) * (1.0f / 3.0);
3133                                 }
3134                         }
3135                 }
3136         }
3137 }
3138
3139 static void R_Shadow_BounceGrid_BlurPixels(void)
3140 {
3141         float *pixels[4];
3142         unsigned int resolution[3];
3143
3144         if (!r_shadow_bouncegrid_state.settings.blur)
3145                 return;
3146         
3147         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
3148
3149         pixels[0] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
3150         pixels[1] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1];
3151         pixels[2] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
3152         pixels[3] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1];
3153
3154         // blur on X
3155         R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[0], pixels[1], 4);
3156         // blur on Y
3157         R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[1], pixels[2], resolution[0] * 4);
3158         // blur on Z
3159         R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[2], pixels[3], resolution[0] * resolution[1] * 4);
3160
3161         // toggle the state, highpixels now points to pixels[3] result
3162         r_shadow_bouncegrid_state.highpixels_index ^= 1;
3163         r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index];
3164 }
3165
3166 static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
3167 {
3168         int floatcolors = r_shadow_bouncegrid_state.settings.floatcolors;
3169         unsigned char *pixelsbgra8 = NULL;
3170         unsigned char *pixelbgra8;
3171         unsigned short *pixelsrgba16f = NULL;
3172         unsigned short *pixelrgba16f;
3173         float *pixelsrgba32f = NULL;
3174         float *highpixels = r_shadow_bouncegrid_state.highpixels;
3175         float *highpixel;
3176         float *bandpixel;
3177         unsigned int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
3178         unsigned int pixelbands = r_shadow_bouncegrid_state.pixelbands;
3179         unsigned int pixelband;
3180         unsigned int x, y, z;
3181         unsigned int index, bandindex;
3182         unsigned int resolution[3];
3183         int c[4];
3184         VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
3185
3186         if (r_shadow_bouncegrid_state.createtexture && r_shadow_bouncegrid_state.texture)
3187         {
3188                 R_FreeTexture(r_shadow_bouncegrid_state.texture);
3189                 r_shadow_bouncegrid_state.texture = NULL;
3190         }
3191
3192         // if bentnormals exist, we need to normalize and bias them for the shader
3193         if (pixelbands > 1)
3194         {
3195                 pixelband = 1;
3196                 for (z = 0;z < resolution[2]-1;z++)
3197                 {
3198                         for (y = 0;y < resolution[1]-1;y++)
3199                         {
3200                                 x = 1;
3201                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
3202                                 highpixel = highpixels + 4*index;
3203                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
3204                                 {
3205                                         // only convert pixels that were hit by photons
3206                                         if (highpixel[3] != 0.0f)
3207                                                 VectorNormalize(highpixel);
3208                                         VectorSet(highpixel, highpixel[0] * 0.5f + 0.5f, highpixel[1] * 0.5f + 0.5f, highpixel[2] * 0.5f + 0.5f);
3209                                         highpixel[pixelsperband * 4 + 3] = 1.0f;
3210                                 }
3211                         }
3212                 }
3213         }
3214
3215         // start by clearing the pixels array - we won't be writing to all of it
3216         //
3217         // then process only the pixels that have at least some color, skipping
3218         // the higher bands for speed on pixels that are black
3219         switch (floatcolors)
3220         {
3221         case 0:
3222                 if (r_shadow_bouncegrid_state.u8pixels == NULL)
3223                         r_shadow_bouncegrid_state.u8pixels = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned char[4]));
3224                 pixelsbgra8 = r_shadow_bouncegrid_state.u8pixels;
3225                 for (pixelband = 0;pixelband < pixelbands;pixelband++)
3226                 {
3227                         if (pixelband == 1)
3228                                 memset(pixelsbgra8 + pixelband * r_shadow_bouncegrid_state.bytesperband, 128, r_shadow_bouncegrid_state.bytesperband);
3229                         else
3230                                 memset(pixelsbgra8 + pixelband * r_shadow_bouncegrid_state.bytesperband, 0, r_shadow_bouncegrid_state.bytesperband);
3231                 }
3232                 for (z = 1;z < resolution[2]-1;z++)
3233                 {
3234                         for (y = 1;y < resolution[1]-1;y++)
3235                         {
3236                                 x = 1;
3237                                 pixelband = 0;
3238                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
3239                                 highpixel = highpixels + 4*index;
3240                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
3241                                 {
3242                                         // only convert pixels that were hit by photons
3243                                         if (VectorLength2(highpixel))
3244                                         {
3245                                                 // normalize the bentnormal now
3246                                                 if (pixelbands > 1)
3247                                                 {
3248                                                         VectorNormalize(highpixel + pixelsperband * 4);
3249                                                         highpixel[pixelsperband * 4 + 3] = 1.0f;
3250                                                 }
3251                                                 // process all of the pixelbands for this pixel
3252                                                 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
3253                                                 {
3254                                                         pixelbgra8 = pixelsbgra8 + 4*bandindex;
3255                                                         bandpixel = highpixels + 4*bandindex;
3256                                                         c[0] = (int)(bandpixel[0]*256.0f);
3257                                                         c[1] = (int)(bandpixel[1]*256.0f);
3258                                                         c[2] = (int)(bandpixel[2]*256.0f);
3259                                                         c[3] = (int)(bandpixel[3]*256.0f);
3260                                                         pixelbgra8[2] = (unsigned char)bound(0, c[0], 255);
3261                                                         pixelbgra8[1] = (unsigned char)bound(0, c[1], 255);
3262                                                         pixelbgra8[0] = (unsigned char)bound(0, c[2], 255);
3263                                                         pixelbgra8[3] = (unsigned char)bound(0, c[3], 255);
3264                                                 }
3265                                         }
3266                                 }
3267                         }
3268                 }
3269
3270                 if (!r_shadow_bouncegrid_state.createtexture)
3271                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixelsbgra8, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
3272                 else
3273                         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);
3274                 break;
3275         case 1:
3276                 if (r_shadow_bouncegrid_state.fp16pixels == NULL)
3277                         r_shadow_bouncegrid_state.fp16pixels = (unsigned short *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
3278                 pixelsrgba16f = r_shadow_bouncegrid_state.fp16pixels;
3279                 memset(pixelsrgba16f, 0, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
3280                 for (z = 1;z < resolution[2]-1;z++)
3281                 {
3282                         for (y = 1;y < resolution[1]-1;y++)
3283                         {
3284                                 x = 1;
3285                                 pixelband = 0;
3286                                 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
3287                                 highpixel = highpixels + 4*index;
3288                                 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
3289                                 {
3290                                         // only convert pixels that were hit by photons
3291                                         if (VectorLength2(highpixel))
3292                                         {
3293                                                 // process all of the pixelbands for this pixel
3294                                                 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
3295                                                 {
3296                                                         // time to have fun with IEEE 754 bit hacking...
3297                                                         union {
3298                                                                 float f[4];
3299                                                                 unsigned int raw[4];
3300                                                         } u;
3301                                                         pixelrgba16f = pixelsrgba16f + 4*bandindex;
3302                                                         bandpixel = highpixels + 4*bandindex;
3303                                                         VectorCopy4(bandpixel, u.f);
3304                                                         VectorCopy4(u.raw, c);
3305                                                         // this math supports negative numbers, snaps denormals to zero
3306                                                         //pixelrgba16f[0] = (unsigned short)(((c[0] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[0] - 0x38000000) >> 13) & 0x7FFF) | ((c[0] >> 16) & 0x8000));
3307                                                         //pixelrgba16f[1] = (unsigned short)(((c[1] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[1] - 0x38000000) >> 13) & 0x7FFF) | ((c[1] >> 16) & 0x8000));
3308                                                         //pixelrgba16f[2] = (unsigned short)(((c[2] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[2] - 0x38000000) >> 13) & 0x7FFF) | ((c[2] >> 16) & 0x8000));
3309                                                         //pixelrgba16f[3] = (unsigned short)(((c[3] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[3] - 0x38000000) >> 13) & 0x7FFF) | ((c[3] >> 16) & 0x8000));
3310                                                         // this math does not support negative
3311                                                         pixelrgba16f[0] = (unsigned short)((c[0] < 0x38000000) ? 0 : ((c[0] - 0x38000000) >> 13));
3312                                                         pixelrgba16f[1] = (unsigned short)((c[1] < 0x38000000) ? 0 : ((c[1] - 0x38000000) >> 13));
3313                                                         pixelrgba16f[2] = (unsigned short)((c[2] < 0x38000000) ? 0 : ((c[2] - 0x38000000) >> 13));
3314                                                         pixelrgba16f[3] = (unsigned short)((c[3] < 0x38000000) ? 0 : ((c[3] - 0x38000000) >> 13));
3315                                                 }
3316                                         }
3317                                 }
3318                         }
3319                 }
3320
3321                 if (!r_shadow_bouncegrid_state.createtexture)
3322                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba16f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
3323                 else
3324                         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);
3325                 break;
3326         case 2:
3327                 // our native format happens to match, so this is easy.
3328                 pixelsrgba32f = highpixels;
3329
3330                 if (!r_shadow_bouncegrid_state.createtexture)
3331                         R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba32f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
3332                 else
3333                         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);
3334                 break;
3335         }
3336
3337         r_shadow_bouncegrid_state.lastupdatetime = realtime;
3338 }
3339
3340 static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t settings, unsigned int range, unsigned int range1, unsigned int range2, int flag)
3341 {
3342         vec3_t bouncerandom[10];
3343         dlight_t *light;
3344         int bouncecount;
3345         int hitsupercontentsmask;
3346         int skipsupercontentsmask;
3347         int skipmaterialflagsmask;
3348         int maxbounce;
3349         int shootparticles;
3350         int shotparticles;
3351         float bounceminimumintensity2;
3352         trace_t cliptrace;
3353         //trace_t cliptrace2;
3354         //trace_t cliptrace3;
3355         unsigned int lightindex;
3356         unsigned int seed;
3357         randomseed_t randomseed;
3358         vec3_t shotcolor;
3359         vec3_t baseshotcolor;
3360         vec3_t surfcolor;
3361         vec3_t clipend;
3362         vec3_t clipstart;
3363         vec3_t clipdiff;
3364         vec_t radius;
3365         vec_t distancetraveled;
3366         vec_t s;
3367         rtlight_t *rtlight;
3368
3369         // compute a seed for the unstable random modes
3370         Math_RandomSeed_FromInts(&randomseed, 0, 0, 0, realtime * 1000.0);
3371         seed = realtime * 1000.0;
3372
3373         r_shadow_bouncegrid_state.numsplatpaths = 0;
3374
3375         // figure out what we want to interact with
3376         if (settings.hitmodels)
3377                 hitsupercontentsmask = SUPERCONTENTS_SOLID;// | SUPERCONTENTS_LIQUIDSMASK;
3378         else
3379                 hitsupercontentsmask = SUPERCONTENTS_SOLID;// | SUPERCONTENTS_LIQUIDSMASK;
3380         skipsupercontentsmask = 0;
3381         skipmaterialflagsmask = MATERIALFLAGMASK_TRANSLUCENT;
3382         maxbounce = settings.maxbounce;
3383
3384         for (lightindex = 0;lightindex < range2;lightindex++)
3385         {
3386                 if (lightindex < range)
3387                 {
3388                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3389                         if (!light)
3390                                 continue;
3391                         rtlight = &light->rtlight;
3392                 }
3393                 else
3394                         rtlight = r_refdef.scene.lights[lightindex - range];
3395                 // note that this code used to keep track of residual photons and
3396                 // distribute them evenly to achieve exactly a desired photon count,
3397                 // but that caused unwanted flickering in dynamic mode
3398                 shootparticles = (int)floor(rtlight->bouncegrid_photons);
3399                 // skip if we won't be shooting any photons
3400                 if (!shootparticles)
3401                         continue;
3402                 radius = rtlight->radius * settings.lightradiusscale;
3403                 //s = settings.particleintensity / shootparticles;
3404                 //VectorScale(rtlight->bouncegrid_photoncolor, s, baseshotcolor);
3405                 VectorCopy(rtlight->bouncegrid_photoncolor, baseshotcolor);
3406                 if (VectorLength2(baseshotcolor) <= 0.0f)
3407                         continue;
3408                 r_refdef.stats[r_stat_bouncegrid_lights]++;
3409                 r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
3410                 // we stop caring about bounces once the brightness goes below this fraction of the original intensity
3411                 bounceminimumintensity2 = VectorLength(baseshotcolor) * settings.bounceminimumintensity2;
3412
3413                 // for seeded random we start the RNG with the position of the light
3414                 if (settings.rng_seed >= 0)
3415                 {
3416                         union
3417                         {
3418                                 unsigned int i[4];
3419                                 float f[4];
3420                         }
3421                         u;
3422                         u.f[0] = rtlight->shadoworigin[0];
3423                         u.f[1] = rtlight->shadoworigin[1];
3424                         u.f[2] = rtlight->shadoworigin[2];
3425                         u.f[3] = 1;
3426                         switch (settings.rng_type)
3427                         {
3428                         default:
3429                         case 0:
3430                                 // we have to shift the seed provided by the user because the result must be odd
3431                                 Math_RandomSeed_FromInts(&randomseed, u.i[0], u.i[1], u.i[2], u.i[3] ^ (settings.rng_seed << 1));
3432                                 break;
3433                         case 1:
3434                                 seed = u.i[0] ^ u.i[1] ^ u.i[2] ^ u.i[3] ^ settings.rng_seed;
3435                                 break;
3436                         }
3437                 }
3438
3439                 for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
3440                 {
3441                         VectorCopy(baseshotcolor, shotcolor);
3442                         VectorCopy(rtlight->shadoworigin, clipstart);
3443                         switch (settings.rng_type)
3444                         {
3445                         default:
3446                         case 0:
3447                                 VectorLehmerRandom(&randomseed, clipend);
3448                                 if (settings.bounceanglediffuse)
3449                                 {
3450                                         // we want random to be stable, so we still have to do all the random we would have done
3451                                         for (bouncecount = 0; bouncecount < maxbounce; bouncecount++)
3452                                                 VectorLehmerRandom(&randomseed, bouncerandom[bouncecount]);
3453                                 }
3454                                 break;
3455                         case 1:
3456                                 VectorCheeseRandom(seed, clipend);
3457                                 if (settings.bounceanglediffuse)
3458                                 {
3459                                         // we want random to be stable, so we still have to do all the random we would have done
3460                                         for (bouncecount = 0; bouncecount < maxbounce; bouncecount++)
3461                                                 VectorCheeseRandom(seed, bouncerandom[bouncecount]);
3462                                 }
3463                                 break;
3464                         }
3465
3466                         // we want a uniform distribution spherically, not merely within the sphere
3467                         if (settings.normalizevectors)
3468                                 VectorNormalize(clipend);
3469
3470                         VectorMA(clipstart, radius, clipend, clipend);
3471                         distancetraveled = 0.0f;
3472                         for (bouncecount = 0;;bouncecount++)
3473                         {
3474                                 r_refdef.stats[r_stat_bouncegrid_traces]++;
3475                                 rtlight->bouncegrid_traces++;
3476                                 //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
3477                                 //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
3478                                 if (settings.staticmode || settings.rng_seed < 0)
3479                                 {
3480                                         // static mode fires a LOT of rays but none of them are identical, so they are not cached
3481                                         // non-stable random in dynamic mode also never reuses a direction, so there's no reason to cache it
3482                                         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);
3483                                 }
3484                                 else
3485                                 {
3486                                         // dynamic mode fires many rays and most will match the cache from the previous frame
3487                                         cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
3488                                 }
3489                                 if (bouncecount > 0 || settings.includedirectlighting)
3490                                 {
3491                                         vec3_t hitpos;
3492                                         VectorCopy(cliptrace.endpos, hitpos);
3493                                         R_Shadow_BounceGrid_AddSplatPath(clipstart, hitpos, shotcolor, distancetraveled);
3494                                 }
3495                                 distancetraveled += VectorDistance(clipstart, cliptrace.endpos);
3496                                 s = VectorDistance(rtlight->shadoworigin, cliptrace.endpos);
3497                                 if (rtlight->bouncegrid_effectiveradius < s)
3498                                         rtlight->bouncegrid_effectiveradius = s;
3499                                 if (cliptrace.fraction >= 1.0f)
3500                                         break;
3501                                 r_refdef.stats[r_stat_bouncegrid_hits]++;
3502                                 rtlight->bouncegrid_hits++;
3503                                 if (bouncecount >= maxbounce)
3504                                         break;
3505                                 // scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
3506                                 // also clamp the resulting color to never add energy, even if the user requests extreme values
3507                                 if (cliptrace.hittexture && cliptrace.hittexture->currentskinframe)
3508                                         VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, surfcolor);
3509                                 else
3510                                         VectorSet(surfcolor, 0.5f, 0.5f, 0.5f);
3511                                 VectorScale(surfcolor, settings.particlebounceintensity, surfcolor);
3512                                 surfcolor[0] = min(surfcolor[0], 1.0f);
3513                                 surfcolor[1] = min(surfcolor[1], 1.0f);
3514                                 surfcolor[2] = min(surfcolor[2], 1.0f);
3515                                 VectorMultiply(shotcolor, surfcolor, shotcolor);
3516                                 if (VectorLength2(shotcolor) <= bounceminimumintensity2)
3517                                         break;
3518                                 r_refdef.stats[r_stat_bouncegrid_bounces]++;
3519                                 if (settings.bounceanglediffuse)
3520                                 {
3521                                         // random direction, primarily along plane normal
3522                                         s = VectorDistance(cliptrace.endpos, clipend);
3523                                         VectorMA(cliptrace.plane.normal, 0.95f, bouncerandom[bouncecount], clipend);
3524                                         VectorNormalize(clipend);
3525                                         VectorScale(clipend, s, clipend);
3526                                 }
3527                                 else
3528                                 {
3529                                         // reflect the remaining portion of the line across plane normal
3530                                         VectorSubtract(clipend, cliptrace.endpos, clipdiff);
3531                                         VectorReflect(clipdiff, 1.0, cliptrace.plane.normal, clipend);
3532                                 }
3533                                 // calculate the new line start and end
3534                                 VectorCopy(cliptrace.endpos, clipstart);
3535                                 VectorAdd(clipstart, clipend, clipend);
3536                         }
3537                 }
3538         }
3539 }
3540
3541 void R_Shadow_UpdateBounceGridTexture(void)
3542 {
3543         int flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
3544         r_shadow_bouncegrid_settings_t settings;
3545         qboolean enable = false;
3546         qboolean settingschanged;
3547         unsigned int range; // number of world lights
3548         unsigned int range1; // number of dynamic lights (or zero if disabled)
3549         unsigned int range2; // range+range1
3550
3551         enable = R_Shadow_BounceGrid_CheckEnable(flag);
3552         
3553         R_Shadow_BounceGrid_GenerateSettings(&settings);
3554         
3555         // changing intensity does not require an update
3556         r_shadow_bouncegrid_state.intensity = r_shadow_bouncegrid_intensity.value;
3557
3558         settingschanged = memcmp(&r_shadow_bouncegrid_state.settings, &settings, sizeof(settings)) != 0;
3559
3560         // when settings change, we free everything as it is just simpler that way.
3561         if (settingschanged || !enable)
3562         {
3563                 // not enabled, make sure we free anything we don't need anymore.
3564                 if (r_shadow_bouncegrid_state.texture)
3565                 {
3566                         R_FreeTexture(r_shadow_bouncegrid_state.texture);
3567                         r_shadow_bouncegrid_state.texture = NULL;
3568                 }
3569                 r_shadow_bouncegrid_state.highpixels = NULL;
3570                 if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
3571                 if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
3572                 if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
3573                 if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
3574                 if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
3575                 r_shadow_bouncegrid_state.maxsplatpaths = 0;
3576                 r_shadow_bouncegrid_state.numpixels = 0;
3577                 r_shadow_bouncegrid_state.directional = false;
3578
3579                 if (!enable)
3580                         return;
3581         }
3582
3583         // if all the settings seem identical to the previous update, return
3584         if (r_shadow_bouncegrid_state.texture && (settings.staticmode || realtime < r_shadow_bouncegrid_state.lastupdatetime + r_shadow_bouncegrid_dynamic_updateinterval.value) && !settingschanged)
3585                 return;
3586
3587         // store the new settings
3588         r_shadow_bouncegrid_state.settings = settings;
3589
3590         R_Shadow_BounceGrid_UpdateSpacing();
3591
3592         // get the range of light numbers we'll be looping over:
3593         // range = static lights
3594         // range1 = dynamic lights (optional)
3595         // range2 = range + range1
3596         range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3597         range1 = settings.staticmode ? 0 : r_refdef.scene.numlights;
3598         range2 = range + range1;
3599
3600         // calculate weighting factors for distributing photons among the lights
3601         R_Shadow_BounceGrid_AssignPhotons(&settings, range, range1, range2, flag);
3602
3603         // trace the photons from lights and accumulate illumination
3604         R_Shadow_BounceGrid_TracePhotons(settings, range, range1, range2, flag);
3605
3606         // clear the texture
3607         R_Shadow_BounceGrid_ClearPixels();
3608         
3609         // accumulate the light splatting into texture
3610         R_Shadow_BounceGrid_PerformSplats();
3611
3612         // apply a mild blur filter to the texture
3613         R_Shadow_BounceGrid_BlurPixels();
3614
3615         // convert the pixels to lower precision and upload the texture
3616         R_Shadow_BounceGrid_ConvertPixelsAndUpload();
3617
3618         // after we compute the static lighting we don't need to keep the highpixels array around
3619         if (settings.staticmode)
3620         {
3621                 r_shadow_bouncegrid_state.highpixels = NULL;
3622                 if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
3623                 if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
3624                 if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
3625                 if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
3626                 if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
3627                 r_shadow_bouncegrid_state.maxsplatpaths = 0;
3628         }
3629 }
3630
3631 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
3632 {
3633         R_Shadow_RenderMode_Reset();
3634         GL_BlendFunc(GL_ONE, GL_ONE);
3635         GL_DepthRange(0, 1);
3636         GL_DepthTest(r_showshadowvolumes.integer < 2);
3637         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
3638         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
3639         GL_CullFace(GL_NONE);
3640         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
3641 }
3642
3643 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
3644 {
3645         R_Shadow_RenderMode_Reset();
3646         GL_BlendFunc(GL_ONE, GL_ONE);
3647         GL_DepthRange(0, 1);
3648         GL_DepthTest(r_showlighting.integer < 2);
3649         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
3650         if (!transparent)
3651                 GL_DepthFunc(GL_EQUAL);
3652         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
3653         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
3654 }
3655
3656 void R_Shadow_RenderMode_End(void)
3657 {
3658         R_Shadow_RenderMode_Reset();
3659         R_Shadow_RenderMode_ActiveLight(NULL);
3660         GL_DepthMask(true);
3661         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3662         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
3663 }
3664
3665 int bboxedges[12][2] =
3666 {
3667         // top
3668         {0, 1}, // +X
3669         {0, 2}, // +Y
3670         {1, 3}, // Y, +X
3671         {2, 3}, // X, +Y
3672         // bottom
3673         {4, 5}, // +X
3674         {4, 6}, // +Y
3675         {5, 7}, // Y, +X
3676         {6, 7}, // X, +Y
3677         // verticals
3678         {0, 4}, // +Z
3679         {1, 5}, // X, +Z
3680         {2, 6}, // Y, +Z
3681         {3, 7}, // XY, +Z
3682 };
3683
3684 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
3685 {
3686         if (!r_shadow_scissor.integer || r_shadow_usingdeferredprepass || r_trippy.integer)
3687         {
3688                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
3689                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
3690                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
3691                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
3692                 return false;
3693         }
3694         if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
3695                 return true; // invisible
3696         if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
3697         || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
3698         || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
3699         || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
3700                 r_refdef.stats[r_stat_lights_scissored]++;
3701         return false;
3702 }
3703
3704 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor)
3705 {
3706         int i;
3707         const float *vertex3f;
3708         const float *normal3f;
3709         float *color4f;
3710         float dist, dot, distintensity, shadeintensity, v[3], n[3];
3711         switch (r_shadow_rendermode)
3712         {
3713         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3714         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3715                 if (VectorLength2(diffusecolor) > 0)
3716                 {
3717                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
3718                         {
3719                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3720                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3721                                 if ((dot = DotProduct(n, v)) < 0)
3722                                 {
3723                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3724                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
3725                                 }
3726                                 else
3727                                         VectorCopy(ambientcolor, color4f);
3728                                 if (r_refdef.fogenabled)
3729                                 {
3730                                         float f;
3731                                         f = RSurf_FogVertex(vertex3f);
3732                                         VectorScale(color4f, f, color4f);
3733                                 }
3734                                 color4f[3] = 1;
3735                         }
3736                 }
3737                 else
3738                 {
3739                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3740                         {
3741                                 VectorCopy(ambientcolor, color4f);
3742                                 if (r_refdef.fogenabled)
3743                                 {
3744                                         float f;
3745                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3746                                         f = RSurf_FogVertex(vertex3f);
3747                                         VectorScale(color4f + 4*i, f, color4f);
3748                                 }
3749                                 color4f[3] = 1;
3750                         }
3751                 }
3752                 break;
3753         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3754                 if (VectorLength2(diffusecolor) > 0)
3755                 {
3756                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
3757                         {
3758                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3759                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3760                                 {
3761                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3762                                         if ((dot = DotProduct(n, v)) < 0)
3763                                         {
3764                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3765                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3766                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3767                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3768                                         }
3769                                         else
3770                                         {
3771                                                 color4f[0] = ambientcolor[0] * distintensity;
3772                                                 color4f[1] = ambientcolor[1] * distintensity;
3773                                                 color4f[2] = ambientcolor[2] * distintensity;
3774                                         }
3775                                         if (r_refdef.fogenabled)
3776                                         {
3777                                                 float f;
3778                                                 f = RSurf_FogVertex(vertex3f);
3779                                                 VectorScale(color4f, f, color4f);
3780                                         }
3781                                 }
3782                                 else
3783                                         VectorClear(color4f);
3784                                 color4f[3] = 1;
3785                         }
3786                 }
3787                 else
3788                 {
3789                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3790                         {
3791                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3792                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3793                                 {
3794                                         color4f[0] = ambientcolor[0] * distintensity;
3795                                         color4f[1] = ambientcolor[1] * distintensity;
3796                                         color4f[2] = ambientcolor[2] * distintensity;
3797                                         if (r_refdef.fogenabled)
3798                                         {
3799                                                 float f;
3800                                                 f = RSurf_FogVertex(vertex3f);
3801                                                 VectorScale(color4f, f, color4f);
3802                                         }
3803                                 }
3804                                 else
3805                                         VectorClear(color4f);
3806                                 color4f[3] = 1;
3807                         }
3808                 }
3809                 break;
3810         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3811                 if (VectorLength2(diffusecolor) > 0)
3812                 {
3813                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
3814                         {
3815                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3816                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3817                                 {
3818                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3819                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3820                                         if ((dot = DotProduct(n, v)) < 0)
3821                                         {
3822                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3823                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3824                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3825                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3826                                         }
3827                                         else
3828                                         {
3829                                                 color4f[0] = ambientcolor[0] * distintensity;
3830                                                 color4f[1] = ambientcolor[1] * distintensity;
3831                                                 color4f[2] = ambientcolor[2] * distintensity;
3832                                         }
3833                                         if (r_refdef.fogenabled)
3834                                         {
3835                                                 float f;
3836                                                 f = RSurf_FogVertex(vertex3f);
3837                                                 VectorScale(color4f, f, color4f);
3838                                         }
3839                                 }
3840                                 else
3841                                         VectorClear(color4f);
3842                                 color4f[3] = 1;
3843                         }
3844                 }
3845                 else
3846                 {
3847                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3848                         {
3849                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3850                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3851                                 {
3852                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3853                                         color4f[0] = ambientcolor[0] * distintensity;
3854                                         color4f[1] = ambientcolor[1] * distintensity;
3855                                         color4f[2] = ambientcolor[2] * distintensity;
3856                                         if (r_refdef.fogenabled)
3857                                         {
3858                                                 float f;
3859                                                 f = RSurf_FogVertex(vertex3f);
3860                                                 VectorScale(color4f, f, color4f);
3861                                         }
3862                                 }
3863                                 else
3864                                         VectorClear(color4f);
3865                                 color4f[3] = 1;
3866                         }
3867                 }
3868                 break;
3869         default:
3870                 break;
3871         }
3872 }
3873
3874 static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
3875 {
3876         // used to display how many times a surface is lit for level design purposes
3877         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3878         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
3879         RSurf_DrawBatch();
3880 }
3881
3882 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])
3883 {
3884         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
3885         R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
3886         RSurf_DrawBatch();
3887 }
3888
3889 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
3890 {
3891         int renders;
3892         int i;
3893         int stop;
3894         int newfirstvertex;
3895         int newlastvertex;
3896         int newnumtriangles;
3897         int *newe;
3898         const int *e;
3899         float *c;
3900         int maxtriangles = 1024;
3901         int newelements[1024*3];
3902         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
3903         for (renders = 0;renders < 4;renders++)
3904         {
3905                 stop = true;
3906                 newfirstvertex = 0;
3907                 newlastvertex = 0;
3908                 newnumtriangles = 0;
3909                 newe = newelements;
3910                 // due to low fillrate on the cards this vertex lighting path is
3911                 // designed for, we manually cull all triangles that do not
3912                 // contain a lit vertex
3913                 // this builds batches of triangles from multiple surfaces and
3914                 // renders them at once
3915                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
3916                 {
3917                         if (VectorLength2(rsurface.passcolor4f + e[0] * 4) + VectorLength2(rsurface.passcolor4f + e[1] * 4) + VectorLength2(rsurface.passcolor4f + e[2] * 4) >= 0.01)
3918                         {
3919                                 if (newnumtriangles)
3920                                 {
3921                                         newfirstvertex = min(newfirstvertex, e[0]);
3922                                         newlastvertex  = max(newlastvertex, e[0]);
3923                                 }
3924                                 else
3925                                 {
3926                                         newfirstvertex = e[0];
3927                                         newlastvertex = e[0];
3928                                 }
3929                                 newfirstvertex = min(newfirstvertex, e[1]);
3930                                 newlastvertex  = max(newlastvertex, e[1]);
3931                                 newfirstvertex = min(newfirstvertex, e[2]);
3932                                 newlastvertex  = max(newlastvertex, e[2]);
3933                                 newe[0] = e[0];
3934                                 newe[1] = e[1];
3935                                 newe[2] = e[2];
3936                                 newnumtriangles++;
3937                                 newe += 3;
3938                                 if (newnumtriangles >= maxtriangles)
3939                                 {
3940                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3941                                         newnumtriangles = 0;
3942                                         newe = newelements;
3943                                         stop = false;
3944                                 }
3945                         }
3946                 }
3947                 if (newnumtriangles >= 1)
3948                 {
3949                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3950                         stop = false;
3951                 }
3952                 // if we couldn't find any lit triangles, exit early
3953                 if (stop)
3954                         break;
3955                 // now reduce the intensity for the next overbright pass
3956                 // we have to clamp to 0 here incase the drivers have improper
3957                 // handling of negative colors
3958                 // (some old drivers even have improper handling of >1 color)
3959                 stop = true;
3960                 for (i = 0, c = rsurface.passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
3961                 {
3962                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
3963                         {
3964                                 c[0] = max(0, c[0] - 1);
3965                                 c[1] = max(0, c[1] - 1);
3966                                 c[2] = max(0, c[2] - 1);
3967                                 stop = false;
3968                         }
3969                         else
3970                                 VectorClear(c);
3971                 }
3972                 // another check...
3973                 if (stop)
3974                         break;
3975         }
3976 }
3977
3978 static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3])
3979 {
3980         // OpenGL 1.1 path (anything)
3981         float ambientcolorbase[3], diffusecolorbase[3];
3982         float ambientcolorpants[3], diffusecolorpants[3];
3983         float ambientcolorshirt[3], diffusecolorshirt[3];
3984         const float *surfacepants = rsurface.texture->render_colormap_pants;
3985         const float *surfaceshirt = rsurface.texture->render_colormap_shirt;
3986         rtexture_t *basetexture = rsurface.texture->basetexture;
3987         rtexture_t *pantstexture = rsurface.texture->pantstexture;
3988         rtexture_t *shirttexture = rsurface.texture->shirttexture;
3989         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
3990         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
3991         VectorCopy(ambientcolor, ambientcolorbase);
3992         VectorCopy(diffusecolor, diffusecolorbase);
3993         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
3994         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
3995         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
3996         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
3997         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (VectorLength2(diffusecolor) > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3998         rsurface.passcolor4f = (float *)R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4]));
3999         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4000         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
4001         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
4002         R_Mesh_TexBind(0, basetexture);
4003         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
4004         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4005         switch(r_shadow_rendermode)
4006         {
4007         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
4008                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
4009                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
4010                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
4011                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4012                 break;
4013         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
4014                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
4015                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
4016                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
4017                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4018                 // fall through
4019         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
4020                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
4021                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
4022                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
4023                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4024                 break;
4025         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
4026                 break;
4027         default:
4028                 break;
4029         }
4030         //R_Mesh_TexBind(0, basetexture);
4031         R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase);
4032         if (dopants)
4033         {
4034                 R_Mesh_TexBind(0, pantstexture);
4035                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants);
4036         }
4037         if (doshirt)
4038         {
4039                 R_Mesh_TexBind(0, shirttexture);
4040                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt);
4041         }
4042 }
4043
4044 extern cvar_t gl_lightmaps;
4045 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
4046 {
4047         qboolean negated;
4048         float ambientcolor[3], diffusecolor[3], specularcolor[3];
4049         VectorM(rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient, rsurface.texture->render_rtlight_diffuse, ambientcolor);
4050         VectorM(rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient), rsurface.texture->render_rtlight_diffuse, diffusecolor);
4051         VectorM(rsurface.rtlight->specularscale, rsurface.texture->render_rtlight_specular, specularcolor);
4052         if (!r_shadow_usenormalmap.integer)
4053         {
4054                 VectorMAM(1.0f, ambientcolor, 1.0f, diffusecolor, ambientcolor);
4055                 VectorClear(diffusecolor);
4056                 VectorClear(specularcolor);
4057         }
4058         VectorMultiply(ambientcolor, rsurface.rtlight->currentcolor, ambientcolor);
4059         VectorMultiply(diffusecolor, rsurface.rtlight->currentcolor, diffusecolor);
4060         VectorMultiply(specularcolor, rsurface.rtlight->currentcolor, specularcolor);
4061         if (VectorLength2(ambientcolor) + VectorLength2(diffusecolor) + VectorLength2(specularcolor) < (1.0f / 1048576.0f))
4062                 return;
4063         negated = (rsurface.rtlight->currentcolor[0] + rsurface.rtlight->currentcolor[1] + rsurface.rtlight->currentcolor[2] < 0) && vid.support.ext_blend_subtract;
4064         if(negated)
4065         {
4066                 VectorNegate(ambientcolor, ambientcolor);
4067                 VectorNegate(diffusecolor, diffusecolor);
4068                 VectorNegate(specularcolor, specularcolor);
4069                 GL_BlendEquationSubtract(true);
4070         }
4071         RSurf_SetupDepthAndCulling();
4072         switch (r_shadow_rendermode)
4073         {
4074         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
4075                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
4076                 R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
4077                 break;
4078         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
4079                 R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor, specularcolor);
4080                 break;
4081         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
4082         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
4083         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
4084         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
4085                 R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor);
4086                 break;
4087         default:
4088                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
4089                 break;
4090         }
4091         if(negated)
4092                 GL_BlendEquationSubtract(false);
4093 }
4094
4095 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)
4096 {
4097         matrix4x4_t tempmatrix = *matrix;
4098         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
4099
4100         // if this light has been compiled before, free the associated data
4101         R_RTLight_Uncompile(rtlight);
4102
4103         // clear it completely to avoid any lingering data
4104         memset(rtlight, 0, sizeof(*rtlight));
4105
4106         // copy the properties
4107         rtlight->matrix_lighttoworld = tempmatrix;
4108         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
4109         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
4110         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
4111         VectorCopy(color, rtlight->color);
4112         rtlight->cubemapname[0] = 0;
4113         if (cubemapname && cubemapname[0])
4114                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
4115         rtlight->shadow = shadow;
4116         rtlight->corona = corona;
4117         rtlight->style = style;
4118         rtlight->isstatic = isstatic;
4119         rtlight->coronasizescale = coronasizescale;
4120         rtlight->ambientscale = ambientscale;
4121         rtlight->diffusescale = diffusescale;
4122         rtlight->specularscale = specularscale;
4123         rtlight->flags = flags;
4124
4125         // compute derived data
4126         //rtlight->cullradius = rtlight->radius;
4127         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
4128         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
4129         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
4130         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
4131         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
4132         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
4133         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
4134 }
4135
4136 // compiles rtlight geometry
4137 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
4138 void R_RTLight_Compile(rtlight_t *rtlight)
4139 {
4140         int i;
4141         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
4142         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
4143         entity_render_t *ent = r_refdef.scene.worldentity;
4144         dp_model_t *model = r_refdef.scene.worldmodel;
4145         unsigned char *data;
4146         shadowmesh_t *mesh;
4147
4148         // compile the light
4149         rtlight->compiled = true;
4150         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
4151         rtlight->static_numleafs = 0;
4152         rtlight->static_numleafpvsbytes = 0;
4153         rtlight->static_leaflist = NULL;
4154         rtlight->static_leafpvs = NULL;
4155         rtlight->static_numsurfaces = 0;
4156         rtlight->static_surfacelist = NULL;
4157         rtlight->static_shadowmap_receivers = 0x3F;
4158         rtlight->static_shadowmap_casters = 0x3F;
4159         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
4160         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
4161         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
4162         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
4163         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
4164         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
4165
4166         if (model && model->GetLightInfo)
4167         {
4168                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
4169                 r_shadow_compilingrtlight = rtlight;
4170                 R_FrameData_SetMark();
4171                 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);
4172                 R_FrameData_ReturnToMark();
4173                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
4174                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
4175                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
4176                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
4177                 rtlight->static_numsurfaces = numsurfaces;
4178                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
4179                 rtlight->static_numleafs = numleafs;
4180                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
4181                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
4182                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
4183                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
4184                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
4185                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
4186                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
4187                 if (rtlight->static_numsurfaces)
4188                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
4189                 if (rtlight->static_numleafs)
4190                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
4191                 if (rtlight->static_numleafpvsbytes)
4192                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
4193                 if (rtlight->static_numshadowtrispvsbytes)
4194                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
4195                 if (rtlight->static_numlighttrispvsbytes)
4196                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
4197                 R_FrameData_SetMark();
4198                 switch (rtlight->shadowmode)
4199                 {
4200                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
4201                         if (model->CompileShadowMap && rtlight->shadow)
4202                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
4203                         break;
4204                 default:
4205                         if (model->CompileShadowVolume && rtlight->shadow)
4206                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
4207                         break;
4208                 }
4209                 R_FrameData_ReturnToMark();
4210                 // now we're done compiling the rtlight
4211                 r_shadow_compilingrtlight = NULL;
4212         }
4213
4214
4215         // use smallest available cullradius - box radius or light radius
4216         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
4217         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
4218
4219         shadowzpasstris = 0;
4220         if (rtlight->static_meshchain_shadow_zpass)
4221                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
4222                         shadowzpasstris += mesh->numtriangles;
4223
4224         shadowzfailtris = 0;
4225         if (rtlight->static_meshchain_shadow_zfail)
4226                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
4227                         shadowzfailtris += mesh->numtriangles;
4228
4229         lighttris = 0;
4230         if (rtlight->static_numlighttrispvsbytes)
4231                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
4232                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
4233                                 lighttris++;
4234
4235         shadowtris = 0;
4236         if (rtlight->static_numshadowtrispvsbytes)
4237                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
4238                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
4239                                 shadowtris++;
4240
4241         if (developer_extra.integer)
4242                 Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
4243 }
4244
4245 void R_RTLight_Uncompile(rtlight_t *rtlight)
4246 {
4247         if (rtlight->compiled)
4248         {
4249                 if (rtlight->static_meshchain_shadow_zpass)
4250                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
4251                 rtlight->static_meshchain_shadow_zpass = NULL;
4252                 if (rtlight->static_meshchain_shadow_zfail)
4253                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
4254                 rtlight->static_meshchain_shadow_zfail = NULL;
4255                 if (rtlight->static_meshchain_shadow_shadowmap)
4256                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
4257                 rtlight->static_meshchain_shadow_shadowmap = NULL;
4258                 // these allocations are grouped
4259                 if (rtlight->static_surfacelist)
4260                         Mem_Free(rtlight->static_surfacelist);
4261                 rtlight->static_numleafs = 0;
4262                 rtlight->static_numleafpvsbytes = 0;
4263                 rtlight->static_leaflist = NULL;
4264                 rtlight->static_leafpvs = NULL;
4265                 rtlight->static_numsurfaces = 0;
4266                 rtlight->static_surfacelist = NULL;
4267                 rtlight->static_numshadowtrispvsbytes = 0;
4268                 rtlight->static_shadowtrispvs = NULL;
4269                 rtlight->static_numlighttrispvsbytes = 0;
4270                 rtlight->static_lighttrispvs = NULL;
4271                 rtlight->compiled = false;
4272         }
4273 }
4274
4275 void R_Shadow_UncompileWorldLights(void)
4276 {
4277         size_t lightindex;
4278         dlight_t *light;
4279         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4280         for (lightindex = 0;lightindex < range;lightindex++)
4281         {
4282                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4283                 if (!light)
4284                         continue;
4285                 R_RTLight_Uncompile(&light->rtlight);
4286         }
4287 }
4288
4289 static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
4290 {
4291         int i, j;
4292         mplane_t plane;
4293         // reset the count of frustum planes
4294         // see rtlight->cached_frustumplanes definition for how much this array
4295         // can hold
4296         rtlight->cached_numfrustumplanes = 0;
4297
4298         if (r_trippy.integer)
4299                 return;
4300
4301         // haven't implemented a culling path for ortho rendering
4302         if (!r_refdef.view.useperspective)
4303         {
4304                 // check if the light is on screen and copy the 4 planes if it is
4305                 for (i = 0;i < 4;i++)
4306                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
4307                                 break;
4308                 if (i == 4)
4309                         for (i = 0;i < 4;i++)
4310                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
4311                 return;
4312         }
4313
4314 #if 1
4315         // generate a deformed frustum that includes the light origin, this is
4316         // used to cull shadow casting surfaces that can not possibly cast a
4317         // shadow onto the visible light-receiving surfaces, which can be a
4318         // performance gain
4319         //
4320         // if the light origin is onscreen the result will be 4 planes exactly
4321         // if the light origin is offscreen on only one axis the result will
4322         // be exactly 5 planes (split-side case)
4323         // if the light origin is offscreen on two axes the result will be
4324         // exactly 4 planes (stretched corner case)
4325         for (i = 0;i < 4;i++)
4326         {
4327                 // quickly reject standard frustum planes that put the light
4328                 // origin outside the frustum
4329                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
4330                         continue;
4331                 // copy the plane
4332                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
4333         }
4334         // if all the standard frustum planes were accepted, the light is onscreen
4335         // otherwise we need to generate some more planes below...
4336         if (rtlight->cached_numfrustumplanes < 4)
4337         {
4338                 // at least one of the stock frustum planes failed, so we need to
4339                 // create one or two custom planes to enclose the light origin
4340                 for (i = 0;i < 4;i++)
4341                 {
4342                         // create a plane using the view origin and light origin, and a
4343                         // single point from the frustum corner set
4344                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
4345                         VectorNormalize(plane.normal);
4346                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
4347                         // see if this plane is backwards and flip it if so
4348                         for (j = 0;j < 4;j++)
4349                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
4350                                         break;
4351                         if (j < 4)
4352                         {
4353                                 VectorNegate(plane.normal, plane.normal);
4354                                 plane.dist *= -1;
4355                                 // flipped plane, test again to see if it is now valid
4356                                 for (j = 0;j < 4;j++)
4357                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
4358                                                 break;
4359                                 // if the plane is still not valid, then it is dividing the
4360                                 // frustum and has to be rejected
4361                                 if (j < 4)
4362                                         continue;
4363                         }
4364                         // we have created a valid plane, compute extra info
4365                         PlaneClassify(&plane);
4366                         // copy the plane
4367                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4368 #if 1
4369                         // if we've found 5 frustum planes then we have constructed a
4370                         // proper split-side case and do not need to keep searching for
4371                         // planes to enclose the light origin
4372                         if (rtlight->cached_numfrustumplanes == 5)
4373                                 break;
4374 #endif
4375                 }
4376         }
4377 #endif
4378
4379 #if 0
4380         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
4381         {
4382                 plane = rtlight->cached_frustumplanes[i];
4383                 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));
4384         }
4385 #endif
4386
4387 #if 0
4388         // now add the light-space box planes if the light box is rotated, as any
4389         // caster outside the oriented light box is irrelevant (even if it passed
4390         // the worldspace light box, which is axial)
4391         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
4392         {
4393                 for (i = 0;i < 6;i++)
4394                 {
4395                         vec3_t v;
4396                         VectorClear(v);
4397                         v[i >> 1] = (i & 1) ? -1 : 1;
4398                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
4399                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
4400                         plane.dist = VectorNormalizeLength(plane.normal);
4401                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
4402                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4403                 }
4404         }
4405 #endif
4406
4407 #if 0
4408         // add the world-space reduced box planes
4409         for (i = 0;i < 6;i++)
4410         {
4411                 VectorClear(plane.normal);
4412                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
4413                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
4414                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4415         }
4416 #endif
4417
4418 #if 0
4419         {
4420         int j, oldnum;
4421         vec3_t points[8];
4422         vec_t bestdist;
4423         // reduce all plane distances to tightly fit the rtlight cull box, which
4424         // is in worldspace
4425         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
4426         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
4427         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
4428         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
4429         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
4430         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
4431         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
4432         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
4433         oldnum = rtlight->cached_numfrustumplanes;
4434         rtlight->cached_numfrustumplanes = 0;
4435         for (j = 0;j < oldnum;j++)
4436         {
4437                 // find the nearest point on the box to this plane
4438                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
4439                 for (i = 1;i < 8;i++)
4440                 {
4441                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
4442                         if (bestdist > dist)
4443                                 bestdist = dist;
4444                 }
4445                 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);
4446                 // if the nearest point is near or behind the plane, we want this
4447                 // plane, otherwise the plane is useless as it won't cull anything
4448                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
4449                 {
4450                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
4451                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
4452                 }
4453         }
4454         }
4455 #endif
4456 }
4457
4458 static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
4459 {
4460         shadowmesh_t *mesh;
4461
4462         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
4463
4464         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
4465         {
4466                 CHECKGLERROR
4467                 GL_CullFace(GL_NONE);
4468                 mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
4469                 for (;mesh;mesh = mesh->next)
4470                 {
4471                         if (!mesh->sidetotals[r_shadow_shadowmapside])
4472                                 continue;
4473                         r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside];
4474                         R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
4475                         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);
4476                 }
4477                 CHECKGLERROR
4478         }
4479         else if (r_refdef.scene.worldentity->model)
4480                 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);
4481
4482         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4483 }
4484
4485 static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
4486 {
4487         qboolean zpass = false;
4488         shadowmesh_t *mesh;
4489         int t, tend;
4490         int surfacelistindex;
4491         msurface_t *surface;
4492
4493         // if triangle neighbors are disabled, shadowvolumes are disabled
4494         if (r_refdef.scene.worldmodel->brush.shadowmesh ? !r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i : !r_refdef.scene.worldmodel->surfmesh.data_neighbor3i)
4495                 return;
4496
4497         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
4498
4499         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
4500         {
4501                 CHECKGLERROR
4502                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
4503                 {
4504                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
4505                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
4506                 }
4507                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
4508                 for (;mesh;mesh = mesh->next)
4509                 {
4510                         r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->numtriangles;
4511                         R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
4512                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
4513                         {
4514                                 // increment stencil if frontface is infront of depthbuffer
4515                                 GL_CullFace(r_refdef.view.cullface_back);
4516                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
4517                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
4518                                 // decrement stencil if backface is infront of depthbuffer
4519                                 GL_CullFace(r_refdef.view.cullface_front);
4520                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
4521                         }
4522                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
4523                         {
4524                                 // decrement stencil if backface is behind depthbuffer
4525                                 GL_CullFace(r_refdef.view.cullface_front);
4526                                 R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
4527                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
4528                                 // increment stencil if frontface is behind depthbuffer
4529                                 GL_CullFace(r_refdef.view.cullface_back);
4530                                 R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
4531                         }
4532                         R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
4533                 }
4534                 CHECKGLERROR
4535         }
4536         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
4537         {
4538                 // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
4539                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
4540                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
4541                 {
4542                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
4543                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
4544                                 if (CHECKPVSBIT(trispvs, t))
4545                                         shadowmarklist[numshadowmark++] = t;
4546                 }
4547                 R_Shadow_VolumeFromList(r_refdef.scene.worldmodel->brush.shadowmesh->numverts, r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles, r_refdef.scene.worldmodel->brush.shadowmesh->vertex3f, r_refdef.scene.worldmodel->brush.shadowmesh->element3i, r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.scene.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist, r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
4548         }
4549         else if (numsurfaces)
4550         {
4551                 r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
4552         }
4553
4554         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4555 }
4556
4557 static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
4558 {
4559         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
4560         vec_t relativeshadowradius;
4561         RSurf_ActiveModelEntity(ent, false, false, false);
4562         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
4563         // we need to re-init the shader for each entity because the matrix changed
4564         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
4565         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
4566         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
4567         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
4568         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
4569         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
4570         relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
4571         switch (r_shadow_rendermode)
4572         {
4573         case R_SHADOW_RENDERMODE_SHADOWMAP2D:
4574                 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
4575                 break;
4576         default:
4577                 ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
4578                 break;
4579         }
4580         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4581 }
4582
4583 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
4584 {
4585         // set up properties for rendering light onto this entity
4586         RSurf_ActiveModelEntity(ent, true, true, false);
4587         Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
4588         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
4589         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
4590         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
4591 }
4592
4593 static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
4594 {
4595         if (!r_refdef.scene.worldmodel->DrawLight)
4596                 return;
4597
4598         // set up properties for rendering light onto this entity
4599         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
4600         rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
4601         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
4602         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
4603         VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
4604
4605         r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
4606
4607         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4608 }
4609
4610 static void R_Shadow_DrawEntityLight(entity_render_t *ent)
4611 {
4612         dp_model_t *model = ent->model;
4613         if (!model->DrawLight)
4614                 return;
4615
4616         R_Shadow_SetupEntityLight(ent);
4617
4618         model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
4619
4620         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4621 }
4622
4623 static void R_Shadow_PrepareLight(rtlight_t *rtlight)
4624 {
4625         int i;
4626         float f;
4627         int numleafs, numsurfaces;
4628         int *leaflist, *surfacelist;
4629         unsigned char *leafpvs;
4630         unsigned char *shadowtrispvs;
4631         unsigned char *lighttrispvs;
4632         //unsigned char *surfacesides;
4633         int numlightentities;
4634         int numlightentities_noselfshadow;
4635         int numshadowentities;
4636         int numshadowentities_noselfshadow;
4637         // FIXME: bounds check lightentities and shadowentities, etc.
4638         static entity_render_t *lightentities[MAX_EDICTS];
4639         static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
4640         static entity_render_t *shadowentities[MAX_EDICTS];
4641         static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
4642         qboolean nolight;
4643         qboolean castshadows;
4644
4645         rtlight->draw = false;
4646         rtlight->cached_numlightentities = 0;
4647         rtlight->cached_numlightentities_noselfshadow = 0;
4648         rtlight->cached_numshadowentities = 0;
4649         rtlight->cached_numshadowentities_noselfshadow = 0;
4650         rtlight->cached_numsurfaces = 0;
4651         rtlight->cached_lightentities = NULL;
4652         rtlight->cached_lightentities_noselfshadow = NULL;
4653         rtlight->cached_shadowentities = NULL;
4654         rtlight->cached_shadowentities_noselfshadow = NULL;
4655         rtlight->cached_shadowtrispvs = NULL;
4656         rtlight->cached_lighttrispvs = NULL;
4657         rtlight->cached_surfacelist = NULL;
4658         rtlight->shadowmapsidesize = 0;
4659
4660         // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
4661         // skip lights that are basically invisible (color 0 0 0)
4662         nolight = VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f);
4663
4664         // loading is done before visibility checks because loading should happen
4665         // all at once at the start of a level, not when it stalls gameplay.
4666         // (especially important to benchmarks)
4667         // compile light
4668         if (rtlight->isstatic && !nolight && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
4669         {
4670                 if (rtlight->compiled)
4671                         R_RTLight_Uncompile(rtlight);
4672                 R_RTLight_Compile(rtlight);
4673         }
4674
4675         // load cubemap
4676         rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
4677
4678         // look up the light style value at this time
4679         f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
4680         VectorScale(rtlight->color, f, rtlight->currentcolor);
4681         /*
4682         if (rtlight->selected)
4683         {
4684                 f = 2 + sin(realtime * M_PI * 4.0);
4685                 VectorScale(rtlight->currentcolor, f, rtlight->currentcolor);
4686         }
4687         */
4688
4689         // skip if lightstyle is currently off
4690         if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
4691                 return;
4692
4693         // skip processing on corona-only lights
4694         if (nolight)
4695                 return;
4696
4697         // skip if the light box is not touching any visible leafs
4698         if (r_shadow_culllights_pvs.integer
4699                 && r_refdef.scene.worldmodel
4700                 && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs
4701                 && !r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, rtlight->cullmins, rtlight->cullmaxs))
4702                 return;
4703
4704         // skip if the light box is not visible to traceline
4705         if (r_shadow_culllights_trace.integer)
4706         {
4707                 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_refdef.view.origin, rtlight->cullmins, rtlight->cullmaxs))
4708                         rtlight->trace_timer = realtime;
4709                 if (realtime - rtlight->trace_timer > r_shadow_culllights_trace_delay.value)
4710                         return;
4711         }
4712
4713         // skip if the light box is off screen
4714         if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
4715                 return;
4716
4717         // in the typical case this will be quickly replaced by GetLightInfo
4718         VectorCopy(rtlight->cullmins, rtlight->cached_cullmins);
4719         VectorCopy(rtlight->cullmaxs, rtlight->cached_cullmaxs);
4720
4721         R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
4722
4723         // don't allow lights to be drawn if using r_shadow_bouncegrid 2, except if we're using static bouncegrid where dynamic lights still need to draw
4724         if (r_shadow_bouncegrid.integer == 2 && (rtlight->isstatic || !r_shadow_bouncegrid_static.integer))
4725                 return;
4726
4727         if (rtlight->compiled && r_shadow_realtime_world_compile.integer)
4728         {
4729                 // compiled light, world available and can receive realtime lighting
4730                 // retrieve leaf information
4731                 numleafs = rtlight->static_numleafs;
4732                 leaflist = rtlight->static_leaflist;
4733                 leafpvs = rtlight->static_leafpvs;
4734                 numsurfaces = rtlight->static_numsurfaces;
4735                 surfacelist = rtlight->static_surfacelist;
4736                 //surfacesides = NULL;
4737                 shadowtrispvs = rtlight->static_shadowtrispvs;
4738                 lighttrispvs = rtlight->static_lighttrispvs;
4739         }
4740         else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->GetLightInfo)
4741         {
4742                 // dynamic light, world available and can receive realtime lighting
4743                 // calculate lit surfaces and leafs
4744                 r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rtlight->cached_cullmins, rtlight->cached_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, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes, rtlight->shadow == 0);
4745                 R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
4746                 leaflist = r_shadow_buffer_leaflist;
4747                 leafpvs = r_shadow_buffer_leafpvs;
4748                 surfacelist = r_shadow_buffer_surfacelist;
4749                 //surfacesides = r_shadow_buffer_surfacesides;
4750                 shadowtrispvs = r_shadow_buffer_shadowtrispvs;
4751                 lighttrispvs = r_shadow_buffer_lighttrispvs;
4752                 // if the reduced leaf bounds are offscreen, skip it
4753                 if (R_CullBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4754                         return;
4755         }
4756         else
4757         {
4758                 // no world
4759                 numleafs = 0;
4760                 leaflist = NULL;
4761                 leafpvs = NULL;
4762                 numsurfaces = 0;
4763                 surfacelist = NULL;
4764                 //surfacesides = NULL;
4765                 shadowtrispvs = NULL;
4766                 lighttrispvs = NULL;
4767         }
4768         // check if light is illuminating any visible leafs
4769         if (numleafs)
4770         {
4771                 for (i = 0; i < numleafs; i++)
4772                         if (r_refdef.viewcache.world_leafvisible[leaflist[i]])
4773                                 break;
4774                 if (i == numleafs)
4775                         return;
4776         }
4777
4778         // make a list of lit entities and shadow casting entities
4779         numlightentities = 0;
4780         numlightentities_noselfshadow = 0;
4781         numshadowentities = 0;
4782         numshadowentities_noselfshadow = 0;
4783
4784         // add dynamic entities that are lit by the light
4785         for (i = 0; i < r_refdef.scene.numentities; i++)
4786         {
4787                 dp_model_t *model;
4788                 entity_render_t *ent = r_refdef.scene.entities[i];
4789                 vec3_t org;
4790                 if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4791                         continue;
4792                 // skip the object entirely if it is not within the valid
4793                 // shadow-casting region (which includes the lit region)
4794                 if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
4795                         continue;
4796                 if (!(model = ent->model))
4797                         continue;
4798                 if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
4799                 {
4800                         // this entity wants to receive light, is visible, and is
4801                         // inside the light box
4802                         // TODO: check if the surfaces in the model can receive light
4803                         // so now check if it's in a leaf seen by the light
4804                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
4805                                 continue;
4806                         if (ent->flags & RENDER_NOSELFSHADOW)
4807                                 lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
4808                         else
4809                                 lightentities[numlightentities++] = ent;
4810                         // since it is lit, it probably also casts a shadow...
4811                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
4812                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4813                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
4814                         {
4815                                 // note: exterior models without the RENDER_NOSELFSHADOW
4816                                 // flag still create a RENDER_NOSELFSHADOW shadow but
4817                                 // are lit normally, this means that they are
4818                                 // self-shadowing but do not shadow other
4819                                 // RENDER_NOSELFSHADOW entities such as the gun
4820                                 // (very weird, but keeps the player shadow off the gun)
4821                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
4822                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
4823                                 else
4824                                         shadowentities[numshadowentities++] = ent;
4825                         }
4826                 }
4827                 else if (ent->flags & RENDER_SHADOW)
4828                 {
4829                         // this entity is not receiving light, but may still need to
4830                         // cast a shadow...
4831                         // TODO: check if the surfaces in the model can cast shadow
4832                         // now check if it is in a leaf seen by the light
4833                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.scene.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.scene.worldmodel, leafpvs, ent->mins, ent->maxs))
4834                                 continue;
4835                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
4836                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4837                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
4838                         {
4839                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
4840                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
4841                                 else
4842                                         shadowentities[numshadowentities++] = ent;
4843                         }
4844                 }
4845         }
4846
4847         // return if there's nothing at all to light
4848         if (numsurfaces + numlightentities + numlightentities_noselfshadow == 0)
4849                 return;
4850
4851         // count this light in the r_speeds
4852         r_refdef.stats[r_stat_lights]++;
4853
4854         // flag it as worth drawing later
4855         rtlight->draw = true;
4856
4857         // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one
4858         castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
4859         if (!castshadows)
4860                 numshadowentities = numshadowentities_noselfshadow = 0;
4861         rtlight->castshadows = castshadows;
4862
4863         // cache all the animated entities that cast a shadow but are not visible
4864         for (i = 0; i < numshadowentities; i++)
4865                 R_AnimCache_GetEntity(shadowentities[i], false, false);
4866         for (i = 0; i < numshadowentities_noselfshadow; i++)
4867                 R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
4868
4869         // we can convert noselfshadow to regular if there are no receivers of that type (or we're using r_shadow_deferred which doesn't support noselfshadow anyway)
4870         if (numshadowentities_noselfshadow > 0 && (numlightentities_noselfshadow == 0 || r_shadow_usingdeferredprepass))
4871         {
4872                 for (i = 0; i < numshadowentities_noselfshadow; i++)
4873                         shadowentities[numshadowentities++] = shadowentities_noselfshadow[i];
4874                 numshadowentities_noselfshadow = 0;
4875         }
4876
4877         // we can convert noselfshadow to regular if there are no casters of that type
4878         if (numlightentities_noselfshadow > 0 && numshadowentities_noselfshadow == 0)
4879         {
4880                 for (i = 0; i < numlightentities_noselfshadow; i++)
4881                         lightentities[numlightentities++] = lightentities_noselfshadow[i];
4882                 numlightentities_noselfshadow = 0;
4883         }
4884
4885         // allocate some temporary memory for rendering this light later in the frame
4886         // reusable buffers need to be copied, static data can be used as-is
4887         rtlight->cached_numlightentities               = numlightentities;
4888         rtlight->cached_numlightentities_noselfshadow  = numlightentities_noselfshadow;
4889         rtlight->cached_numshadowentities              = numshadowentities;
4890         rtlight->cached_numshadowentities_noselfshadow = numshadowentities_noselfshadow;
4891         rtlight->cached_numsurfaces                    = numsurfaces;
4892         rtlight->cached_lightentities                  = (entity_render_t**)R_FrameData_Store(numlightentities*sizeof(entity_render_t*), (void*)lightentities);
4893         rtlight->cached_lightentities_noselfshadow     = (entity_render_t**)R_FrameData_Store(numlightentities_noselfshadow*sizeof(entity_render_t*), (void*)lightentities_noselfshadow);
4894         rtlight->cached_shadowentities                 = (entity_render_t**)R_FrameData_Store(numshadowentities*sizeof(entity_render_t*), (void*)shadowentities);
4895         rtlight->cached_shadowentities_noselfshadow    = (entity_render_t**)R_FrameData_Store(numshadowentities_noselfshadow*sizeof(entity_render_t *), (void*)shadowentities_noselfshadow);
4896         if (shadowtrispvs == r_shadow_buffer_shadowtrispvs)
4897         {
4898                 int numshadowtrispvsbytes = (((r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles) + 7) >> 3);
4899                 int numlighttrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
4900                 rtlight->cached_shadowtrispvs                  =   (unsigned char *)R_FrameData_Store(numshadowtrispvsbytes, shadowtrispvs);
4901                 rtlight->cached_lighttrispvs                   =   (unsigned char *)R_FrameData_Store(numlighttrispvsbytes, lighttrispvs);
4902                 rtlight->cached_surfacelist                    =              (int*)R_FrameData_Store(numsurfaces*sizeof(int), (void*)surfacelist);
4903         }
4904         else
4905         {
4906                 // compiled light data
4907                 rtlight->cached_shadowtrispvs = shadowtrispvs;
4908                 rtlight->cached_lighttrispvs = lighttrispvs;
4909                 rtlight->cached_surfacelist = surfacelist;
4910         }
4911
4912         if (R_Shadow_ShadowMappingEnabled())
4913         {
4914                 // figure out the shadowmapping parameters for this light
4915                 vec3_t nearestpoint;
4916                 vec_t distance;
4917                 int lodlinear;
4918                 nearestpoint[0] = bound(rtlight->cullmins[0], r_refdef.view.origin[0], rtlight->cullmaxs[0]);
4919                 nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
4920                 nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
4921                 distance = VectorDistance(nearestpoint, r_refdef.view.origin);
4922                 lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance / rtlight->radius));
4923                 //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
4924                 lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
4925                 rtlight->shadowmapsidesize = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
4926                 // shadowmapatlas* variables will be set by R_Shadow_PrepareLights()
4927         }
4928 }
4929
4930 static void R_Shadow_DrawLightShadowMaps(rtlight_t *rtlight)
4931 {
4932         int i;
4933         int numsurfaces;
4934         unsigned char *shadowtrispvs, *lighttrispvs, *surfacesides;
4935         int numlightentities;
4936         int numlightentities_noselfshadow;
4937         int numshadowentities;
4938         int numshadowentities_noselfshadow;
4939         entity_render_t **lightentities;
4940         entity_render_t **lightentities_noselfshadow;
4941         entity_render_t **shadowentities;
4942         entity_render_t **shadowentities_noselfshadow;
4943         int *surfacelist;
4944         static unsigned char entitysides[MAX_EDICTS];
4945         static unsigned char entitysides_noselfshadow[MAX_EDICTS];
4946         float borderbias;
4947         int side;
4948         int size;
4949         int castermask;
4950         int receivermask;
4951         matrix4x4_t radiustolight;
4952
4953         // check if we cached this light this frame (meaning it is worth drawing)
4954         if (!rtlight->draw || !rtlight->castshadows)
4955                 return;
4956
4957         // if PrepareLights could not find any space for this shadowmap, we may as well mark it as not casting shadows...
4958         if (rtlight->shadowmapatlassidesize == 0)
4959         {
4960                 rtlight->castshadows = false;
4961                 return;
4962         }
4963
4964         // set up a scissor rectangle for this light
4965         if (R_Shadow_ScissorForBBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4966                 return;
4967
4968         // don't let sound skip if going slow
4969         if (r_refdef.scene.extraupdate)
4970                 S_ExtraUpdate();
4971
4972         numlightentities = rtlight->cached_numlightentities;
4973         numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
4974         numshadowentities = rtlight->cached_numshadowentities;
4975         numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
4976         numsurfaces = rtlight->cached_numsurfaces;
4977         lightentities = rtlight->cached_lightentities;
4978         lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
4979         shadowentities = rtlight->cached_shadowentities;
4980         shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
4981         shadowtrispvs = rtlight->cached_shadowtrispvs;
4982         lighttrispvs = rtlight->cached_lighttrispvs;
4983         surfacelist = rtlight->cached_surfacelist;
4984
4985         // make this the active rtlight for rendering purposes
4986         R_Shadow_RenderMode_ActiveLight(rtlight);
4987
4988         radiustolight = rtlight->matrix_worldtolight;
4989         Matrix4x4_Abs(&radiustolight);
4990
4991         size = rtlight->shadowmapatlassidesize;
4992         borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
4993
4994         surfacesides = NULL;
4995         castermask = 0;
4996         receivermask = 0;
4997         if (numsurfaces)
4998         {
4999                 if (rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
5000                 {
5001                         castermask = rtlight->static_shadowmap_casters;
5002                         receivermask = rtlight->static_shadowmap_receivers;
5003                 }
5004                 else
5005                 {
5006                         surfacesides = r_shadow_buffer_surfacesides;
5007                         for (i = 0; i < numsurfaces; i++)
5008                         {
5009                                 msurface_t *surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[i];
5010                                 surfacesides[i] = R_Shadow_CalcBBoxSideMask(surface->mins, surface->maxs, &rtlight->matrix_worldtolight, &radiustolight, borderbias);
5011                                 castermask |= surfacesides[i];
5012                                 receivermask |= surfacesides[i];
5013                         }
5014                 }
5015         }
5016
5017         for (i = 0; i < numlightentities && receivermask < 0x3F; i++)
5018                 receivermask |= R_Shadow_CalcEntitySideMask(lightentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
5019         for (i = 0; i < numlightentities_noselfshadow && receivermask < 0x3F; i++)
5020                 receivermask |= R_Shadow_CalcEntitySideMask(lightentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
5021
5022         receivermask &= R_Shadow_CullFrustumSides(rtlight, size, r_shadow_shadowmapborder);
5023
5024         if (receivermask)
5025         {
5026                 for (i = 0; i < numshadowentities; i++)
5027                         castermask |= (entitysides[i] = R_Shadow_CalcEntitySideMask(shadowentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
5028                 for (i = 0; i < numshadowentities_noselfshadow; i++)
5029                         castermask |= (entitysides_noselfshadow[i] = R_Shadow_CalcEntitySideMask(shadowentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
5030         }
5031
5032         // there is no need to render shadows for sides that have no receivers...
5033         castermask &= receivermask;
5034
5035         //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
5036
5037         // render shadow casters into shadowmaps for this light
5038         for (side = 0; side < 6; side++)
5039         {
5040                 int bit = 1 << side;
5041                 if (castermask & bit)
5042                 {
5043                         R_Shadow_RenderMode_ShadowMap(side, size, rtlight->shadowmapatlasposition[0], rtlight->shadowmapatlasposition[1]);
5044                         if (numsurfaces)
5045                                 R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
5046                         for (i = 0; i < numshadowentities; i++)
5047                                 if (entitysides[i] & bit)
5048                                         R_Shadow_DrawEntityShadow(shadowentities[i]);
5049                         for (i = 0; i < numshadowentities_noselfshadow; i++)
5050                                 if (entitysides_noselfshadow[i] & bit)
5051                                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
5052                 }
5053         }
5054         // additionally if there are any noselfshadow casters we have to render a second set of shadowmaps without those :(
5055         if (numshadowentities_noselfshadow)
5056         {
5057                 for (side = 0; side < 6; side++)
5058                 {
5059                         int bit = 1 << side;
5060                         if (castermask & bit)
5061                         {
5062                                 R_Shadow_RenderMode_ShadowMap(side, size, rtlight->shadowmapatlasposition[0] + size * 2, rtlight->shadowmapatlasposition[1]);
5063                                 if (numsurfaces)
5064                                         R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
5065                                 for (i = 0; i < numshadowentities; i++)
5066                                         if (entitysides[i] & bit)
5067                                                 R_Shadow_DrawEntityShadow(shadowentities[i]);
5068                         }
5069                 }
5070         }
5071 }
5072
5073 static void R_Shadow_DrawLight(rtlight_t *rtlight)
5074 {
5075         int i;
5076         int numsurfaces;
5077         unsigned char *shadowtrispvs, *lighttrispvs;
5078         int numlightentities;
5079         int numlightentities_noselfshadow;
5080         int numshadowentities;
5081         int numshadowentities_noselfshadow;
5082         entity_render_t **lightentities;
5083         entity_render_t **lightentities_noselfshadow;
5084         entity_render_t **shadowentities;
5085         entity_render_t **shadowentities_noselfshadow;
5086         int *surfacelist;
5087         qboolean castshadows;
5088
5089         // check if we cached this light this frame (meaning it is worth drawing)
5090         if (!rtlight->draw)
5091                 return;
5092
5093         // set up a scissor rectangle for this light
5094         if (R_Shadow_ScissorForBBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
5095                 return;
5096
5097         // don't let sound skip if going slow
5098         if (r_refdef.scene.extraupdate)
5099                 S_ExtraUpdate();
5100
5101         numlightentities = rtlight->cached_numlightentities;
5102         numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
5103         numshadowentities = rtlight->cached_numshadowentities;
5104         numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
5105         numsurfaces = rtlight->cached_numsurfaces;
5106         lightentities = rtlight->cached_lightentities;
5107         lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
5108         shadowentities = rtlight->cached_shadowentities;
5109         shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
5110         shadowtrispvs = rtlight->cached_shadowtrispvs;
5111         lighttrispvs = rtlight->cached_lighttrispvs;
5112         surfacelist = rtlight->cached_surfacelist;
5113         castshadows = rtlight->castshadows;
5114
5115         // make this the active rtlight for rendering purposes
5116         R_Shadow_RenderMode_ActiveLight(rtlight);
5117
5118         if (r_showshadowvolumes.integer && r_refdef.view.showdebug && numsurfaces + numshadowentities + numshadowentities_noselfshadow && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows))
5119         {
5120                 // optionally draw visible shape of the shadow volumes
5121                 // for performance analysis by level designers
5122                 R_Shadow_RenderMode_VisibleShadowVolumes();
5123                 if (numsurfaces)
5124                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
5125                 for (i = 0;i < numshadowentities;i++)
5126                         R_Shadow_DrawEntityShadow(shadowentities[i]);
5127                 for (i = 0;i < numshadowentities_noselfshadow;i++)
5128                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
5129                 R_Shadow_RenderMode_VisibleLighting(false, false);
5130         }
5131
5132         if (r_showlighting.integer && r_refdef.view.showdebug && numsurfaces + numlightentities + numlightentities_noselfshadow)
5133         {
5134                 // optionally draw the illuminated areas
5135                 // for performance analysis by level designers
5136                 R_Shadow_RenderMode_VisibleLighting(false, false);
5137                 if (numsurfaces)
5138                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
5139                 for (i = 0;i < numlightentities;i++)
5140                         R_Shadow_DrawEntityLight(lightentities[i]);
5141                 for (i = 0;i < numlightentities_noselfshadow;i++)
5142                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
5143         }
5144
5145         if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
5146         {
5147                 float borderbias;
5148                 int size;
5149                 float shadowmapoffsetnoselfshadow = 0;
5150                 matrix4x4_t radiustolight = rtlight->matrix_worldtolight;
5151                 Matrix4x4_Abs(&radiustolight);
5152
5153                 size = rtlight->shadowmapatlassidesize;
5154                 borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
5155
5156                 //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
5157
5158                 if (rtlight->cached_numshadowentities_noselfshadow)
5159                         shadowmapoffsetnoselfshadow = rtlight->shadowmapatlassidesize * 2;
5160
5161                 // render lighting using the depth texture as shadowmap
5162                 // draw lighting in the unmasked areas
5163                 if (numsurfaces + numlightentities)
5164                 {
5165                         R_Shadow_RenderMode_Lighting(false, false, true, false);
5166                         // draw lighting in the unmasked areas
5167                         if (numsurfaces)
5168                                 R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
5169                         for (i = 0; i < numlightentities; i++)
5170                                 R_Shadow_DrawEntityLight(lightentities[i]);
5171                 }
5172                 // offset to the noselfshadow part of the atlas and draw those too
5173                 if (numlightentities_noselfshadow)
5174                 {
5175                         R_Shadow_RenderMode_Lighting(false, false, true, true);
5176                         for (i = 0; i < numlightentities_noselfshadow; i++)
5177                                 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
5178                 }
5179
5180                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
5181                 if (r_shadow_usingdeferredprepass)
5182                         R_Shadow_RenderMode_DrawDeferredLight(true);
5183         }
5184         else if (castshadows && vid.stencil)
5185         {
5186                 // draw stencil shadow volumes to mask off pixels that are in shadow
5187                 // so that they won't receive lighting
5188                 GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
5189                 R_Shadow_ClearStencil();
5190
5191                 if (numsurfaces)
5192                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
5193                 for (i = 0;i < numshadowentities;i++)
5194                         R_Shadow_DrawEntityShadow(shadowentities[i]);
5195
5196                 // draw lighting in the unmasked areas
5197                 R_Shadow_RenderMode_Lighting(true, false, false, false);
5198                 for (i = 0;i < numlightentities_noselfshadow;i++)
5199                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
5200
5201                 for (i = 0;i < numshadowentities_noselfshadow;i++)
5202                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
5203
5204                 // draw lighting in the unmasked areas
5205                 R_Shadow_RenderMode_Lighting(true, false, false, false);
5206                 if (numsurfaces)
5207                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
5208                 for (i = 0;i < numlightentities;i++)
5209                         R_Shadow_DrawEntityLight(lightentities[i]);
5210
5211                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
5212                 if (r_shadow_usingdeferredprepass)
5213                         R_Shadow_RenderMode_DrawDeferredLight(false);
5214         }
5215         else
5216         {
5217                 // draw lighting in the unmasked areas
5218                 R_Shadow_RenderMode_Lighting(false, false, false, false);
5219                 if (numsurfaces)
5220                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
5221                 for (i = 0;i < numlightentities;i++)
5222                         R_Shadow_DrawEntityLight(lightentities[i]);
5223                 for (i = 0;i < numlightentities_noselfshadow;i++)
5224                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
5225
5226                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
5227                 if (r_shadow_usingdeferredprepass)
5228                         R_Shadow_RenderMode_DrawDeferredLight(false);
5229         }
5230 }
5231
5232 static void R_Shadow_FreeDeferred(void)
5233 {
5234         R_Mesh_DestroyFramebufferObject(r_shadow_prepassgeometryfbo);
5235         r_shadow_prepassgeometryfbo = 0;
5236
5237         R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusespecularfbo);
5238         r_shadow_prepasslightingdiffusespecularfbo = 0;
5239
5240         R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusefbo);
5241         r_shadow_prepasslightingdiffusefbo = 0;
5242
5243         if (r_shadow_prepassgeometrydepthbuffer)
5244                 R_FreeTexture(r_shadow_prepassgeometrydepthbuffer);
5245         r_shadow_prepassgeometrydepthbuffer = NULL;
5246
5247         if (r_shadow_prepassgeometrynormalmaptexture)
5248                 R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
5249         r_shadow_prepassgeometrynormalmaptexture = NULL;
5250
5251         if (r_shadow_prepasslightingdiffusetexture)
5252                 R_FreeTexture(r_shadow_prepasslightingdiffusetexture);
5253         r_shadow_prepasslightingdiffusetexture = NULL;
5254
5255         if (r_shadow_prepasslightingspeculartexture)
5256                 R_FreeTexture(r_shadow_prepasslightingspeculartexture);
5257         r_shadow_prepasslightingspeculartexture = NULL;
5258 }
5259
5260 void R_Shadow_DrawPrepass(void)
5261 {
5262         int i;
5263         int lnum;
5264         entity_render_t *ent;
5265         float clearcolor[4];
5266
5267         R_Mesh_ResetTextureState();
5268         GL_DepthMask(true);
5269         GL_ColorMask(1,1,1,1);
5270         GL_BlendFunc(GL_ONE, GL_ZERO);
5271         GL_Color(1,1,1,1);
5272         GL_DepthTest(true);
5273         R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5274         Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
5275         GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
5276         if (r_timereport_active)
5277                 R_TimeReport("prepasscleargeom");
5278
5279         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawPrepass)
5280                 r_refdef.scene.worldmodel->DrawPrepass(r_refdef.scene.worldentity);
5281         if (r_timereport_active)
5282                 R_TimeReport("prepassworld");
5283
5284         for (i = 0;i < r_refdef.scene.numentities;i++)
5285         {
5286                 if (!r_refdef.viewcache.entityvisible[i])
5287                         continue;
5288                 ent = r_refdef.scene.entities[i];
5289                 if (ent->model && ent->model->DrawPrepass != NULL)
5290                         ent->model->DrawPrepass(ent);
5291         }
5292
5293         if (r_timereport_active)
5294                 R_TimeReport("prepassmodels");
5295
5296         GL_DepthMask(false);
5297         GL_ColorMask(1,1,1,1);
5298         GL_Color(1,1,1,1);
5299         GL_DepthTest(true);
5300         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5301         Vector4Set(clearcolor, 0, 0, 0, 0);
5302         GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
5303         if (r_timereport_active)
5304                 R_TimeReport("prepassclearlit");
5305
5306         R_Shadow_RenderMode_Begin();
5307
5308         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5309                 R_Shadow_DrawLight(r_shadow_scenelightlist[lnum]);
5310
5311         R_Shadow_RenderMode_End();
5312
5313         if (r_timereport_active)
5314                 R_TimeReport("prepasslights");
5315 }
5316
5317 #define MAX_SCENELIGHTS 65536
5318 qboolean R_Shadow_PrepareLights_AddSceneLight(rtlight_t *rtlight)
5319 {
5320         if (r_shadow_scenemaxlights <= r_shadow_scenenumlights)
5321         {
5322                 if (r_shadow_scenenumlights >= MAX_SCENELIGHTS)
5323                         return false;
5324                 r_shadow_scenemaxlights *= 2;
5325                 r_shadow_scenemaxlights = bound(1024, r_shadow_scenemaxlights, MAX_SCENELIGHTS);
5326                 r_shadow_scenelightlist = (rtlight_t **)Mem_Realloc(r_main_mempool, r_shadow_scenelightlist, r_shadow_scenemaxlights * sizeof(rtlight_t *));
5327         }
5328         r_shadow_scenelightlist[r_shadow_scenenumlights++] = rtlight;
5329         return true;
5330 }
5331
5332 void R_Shadow_DrawLightSprites(void);
5333 void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5334 {
5335         int flag;
5336         int lnum;
5337         size_t lightindex;
5338         dlight_t *light;
5339         size_t range;
5340         float f;
5341
5342         int shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
5343         int shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
5344         int shadowmapmaxsize = bound(shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, shadowmaptexturesize / 8);
5345
5346         if (r_shadow_shadowmaptexturesize != shadowmaptexturesize ||
5347                 (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
5348                 r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) ||
5349                 r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
5350                 r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
5351                 r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
5352                 r_shadow_shadowmapborder != shadowmapborder ||
5353                 r_shadow_shadowmapmaxsize != shadowmapmaxsize ||
5354                 r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
5355                 R_Shadow_FreeShadowMaps();
5356
5357         r_shadow_fb_fbo = fbo;
5358         r_shadow_fb_depthtexture = depthtexture;
5359         r_shadow_fb_colortexture = colortexture;
5360
5361         r_shadow_usingshadowmaportho = false;
5362
5363         switch (vid.renderpath)
5364         {
5365         case RENDERPATH_GL20:
5366         case RENDERPATH_D3D9:
5367         case RENDERPATH_D3D10:
5368         case RENDERPATH_D3D11:
5369         case RENDERPATH_SOFT:
5370 #ifndef USE_GLES2
5371                 if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
5372                 {
5373                         r_shadow_usingdeferredprepass = false;
5374                         if (r_shadow_prepass_width)
5375                                 R_Shadow_FreeDeferred();
5376                         r_shadow_prepass_width = r_shadow_prepass_height = 0;
5377                         break;
5378                 }
5379
5380                 if (r_shadow_prepass_width != vid.width || r_shadow_prepass_height != vid.height)
5381                 {
5382                         R_Shadow_FreeDeferred();
5383
5384                         r_shadow_usingdeferredprepass = true;
5385                         r_shadow_prepass_width = vid.width;
5386                         r_shadow_prepass_height = vid.height;
5387                         r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
5388                         r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER32F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
5389                         r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
5390                         r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
5391
5392                         // set up the geometry pass fbo (depth + normalmap)
5393                         r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5394                         R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5395                         // render depth into a renderbuffer and other important properties into the normalmap texture
5396
5397                         // set up the lighting pass fbo (diffuse + specular)
5398                         r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5399                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5400                         // render diffuse into one texture and specular into another,
5401                         // with depth and normalmap bound as textures,
5402                         // with depth bound as attachment as well
5403
5404                         // set up the lighting pass fbo (diffuse)
5405                         r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5406                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5407                         // render diffuse into one texture,
5408                         // with depth and normalmap bound as textures,
5409                         // with depth bound as attachment as well
5410                 }
5411 #endif
5412                 break;
5413         case RENDERPATH_GL11:
5414         case RENDERPATH_GL13:
5415         case RENDERPATH_GLES1:
5416         case RENDERPATH_GLES2:
5417                 r_shadow_usingdeferredprepass = false;
5418                 break;
5419         }
5420
5421         R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
5422
5423         r_shadow_scenenumlights = 0;
5424         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
5425         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5426         for (lightindex = 0; lightindex < range; lightindex++)
5427         {
5428                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5429                 if (light && (light->flags & flag))
5430                 {
5431                         R_Shadow_PrepareLight(&light->rtlight);
5432                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5433                 }
5434         }
5435         if (r_refdef.scene.rtdlight)
5436         {
5437                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5438                 {
5439                         R_Shadow_PrepareLight(r_refdef.scene.lights[lnum]);
5440                         R_Shadow_PrepareLights_AddSceneLight(r_refdef.scene.lights[lnum]);
5441                 }
5442         }
5443         else if (gl_flashblend.integer)
5444         {
5445                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5446                 {
5447                         rtlight_t *rtlight = r_refdef.scene.lights[lnum];
5448                         f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
5449                         VectorScale(rtlight->color, f, rtlight->currentcolor);
5450                 }
5451         }
5452
5453         // when debugging a single light, we still want to run the prepare, so we only replace the light list afterward...
5454         if (r_shadow_debuglight.integer >= 0)
5455         {
5456                 r_shadow_scenenumlights = 0;
5457                 lightindex = r_shadow_debuglight.integer;
5458                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5459                 if (light)
5460                 {
5461                         R_Shadow_PrepareLight(&light->rtlight);
5462                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5463                 }
5464         }
5465
5466         // if we're doing shadowmaps we need to prepare the atlas layout now
5467         if (R_Shadow_ShadowMappingEnabled())
5468         {
5469                 int lod;
5470
5471                 // allocate shadowmaps in the atlas now
5472                 // we may have to make multiple attempts to fit the shadowmaps in the limited space of the atlas, this will appear as lod popping of all shadowmaps whenever it changes, but at least we can still cast shadows from all lights...
5473                 for (lod = 0; lod < 16; lod++)
5474                 {
5475                         int packing_success = 0;
5476                         int packing_failure = 0;
5477                         Mod_AllocLightmap_Reset(&r_shadow_shadowmapatlas_state);
5478                         // we actually have to reserve space for the R_DrawModelShadowMaps if that feature is active, it uses 0,0 so this is easy.
5479                         if (r_shadow_shadowmapatlas_modelshadows_size)
5480                                 Mod_AllocLightmap_Block(&r_shadow_shadowmapatlas_state, r_shadow_shadowmapatlas_modelshadows_size, r_shadow_shadowmapatlas_modelshadows_size, &r_shadow_shadowmapatlas_modelshadows_x, &r_shadow_shadowmapatlas_modelshadows_y);
5481                         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5482                         {
5483                                 rtlight_t *rtlight = r_shadow_scenelightlist[lnum];
5484                                 int size = rtlight->shadowmapsidesize >> lod;
5485                                 int width, height;
5486                                 if (!rtlight->castshadows)
5487                                         continue;
5488                                 size = bound(r_shadow_shadowmapborder, size, r_shadow_shadowmaptexturesize);
5489                                 width = size * 2;
5490                                 height = size * 3;
5491                                 // when there are noselfshadow entities in the light bounds, we have to render two separate sets of shadowmaps :(
5492                                 if (rtlight->cached_numshadowentities_noselfshadow)
5493                                         width *= 2;
5494                                 if (Mod_AllocLightmap_Block(&r_shadow_shadowmapatlas_state, width, height, &rtlight->shadowmapatlasposition[0], &rtlight->shadowmapatlasposition[1]))
5495                                 {
5496                                         rtlight->shadowmapatlassidesize = size;
5497                                         packing_success++;
5498                                 }
5499                                 else
5500                                 {
5501                                         // note down that we failed to pack this one, it will have to disable shadows
5502                                         rtlight->shadowmapatlassidesize = 0;
5503                                         packing_failure++;
5504                                 }
5505                         }
5506                         // generally everything fits and we stop here on the first iteration
5507                         if (packing_failure == 0)
5508                                 break;
5509                 }
5510         }
5511
5512         if (r_editlights.integer)
5513                 R_Shadow_DrawLightSprites();
5514 }
5515
5516 void R_Shadow_DrawShadowMaps(void)
5517 {
5518         R_Shadow_RenderMode_Begin();
5519         R_Shadow_RenderMode_ActiveLight(NULL);
5520
5521         // now that we have a layout of shadowmaps in the atlas, we can render the shadowmaps
5522         R_Shadow_ClearShadowMapTexture();
5523
5524         // render model shadowmaps (r_shadows 2) if desired which will be sampled in the forward pass
5525         if (r_shadow_shadowmapatlas_modelshadows_size)
5526         {
5527                 R_Shadow_DrawModelShadowMaps();
5528                 // don't let sound skip if going slow
5529                 if (r_refdef.scene.extraupdate)
5530                         S_ExtraUpdate();
5531         }
5532
5533         if (R_Shadow_ShadowMappingEnabled())
5534         {
5535                 int lnum;
5536                 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5537                         R_Shadow_DrawLightShadowMaps(r_shadow_scenelightlist[lnum]);
5538         }
5539
5540         R_Shadow_RenderMode_End();
5541 }
5542
5543 void R_Shadow_DrawLights(void)
5544 {
5545         int lnum;
5546
5547         R_Shadow_RenderMode_Begin();
5548
5549         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5550                 R_Shadow_DrawLight(r_shadow_scenelightlist[lnum]);
5551
5552         R_Shadow_RenderMode_End();
5553 }
5554
5555 #define MAX_MODELSHADOWS 1024
5556 static int r_shadow_nummodelshadows;
5557 static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS];
5558
5559 void R_Shadow_PrepareModelShadows(void)
5560 {
5561         int i;
5562         float scale, size, radius, dot1, dot2;
5563         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5564         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
5565         entity_render_t *ent;
5566
5567         r_shadow_nummodelshadows = 0;
5568         r_shadow_shadowmapatlas_modelshadows_size = 0;
5569
5570         if (!r_refdef.scene.numentities || r_refdef.scene.lightmapintensity <= 0.0f || r_shadows.integer <= 0)
5571                 return;
5572
5573         switch (r_shadow_shadowmode)
5574         {
5575         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
5576                 if (r_shadows.integer >= 2)
5577                         break;
5578                 // fall through
5579         case R_SHADOW_SHADOWMODE_STENCIL:
5580                 if (!vid.stencil)
5581                         return;
5582                 for (i = 0; i < r_refdef.scene.numentities; i++)
5583                 {
5584                         ent = r_refdef.scene.entities[i];
5585                         if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5586                         {
5587                                 if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5588                                         break;
5589                                 r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5590                                 R_AnimCache_GetEntity(ent, false, false);
5591                         }
5592                 }
5593                 return;
5594         default:
5595                 return;
5596         }
5597
5598         size = r_shadow_shadowmaptexturesize / 4;
5599         scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
5600         radius = 0.5f * size / scale;
5601
5602         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5603         VectorCopy(prvmshadowdir, shadowdir);
5604         VectorNormalize(shadowdir);
5605         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5606         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5607         if (fabs(dot1) <= fabs(dot2))
5608                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5609         else
5610                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5611         VectorNormalize(shadowforward);
5612         CrossProduct(shadowdir, shadowforward, shadowright);
5613         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5614         VectorCopy(prvmshadowfocus, shadowfocus);
5615         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5616         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5617         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5618         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5619         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5620                 dot1 = 1;
5621         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5622
5623         shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5624         shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5625         shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5626         shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5627         shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5628         shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5629
5630         for (i = 0; i < r_refdef.scene.numentities; i++)
5631         {
5632                 ent = r_refdef.scene.entities[i];
5633                 if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
5634                         continue;
5635                 // cast shadows from anything of the map (submodels are optional)
5636                 if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5637                 {
5638                         if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5639                                 break;
5640                         r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5641                         R_AnimCache_GetEntity(ent, false, false);
5642                 }
5643         }
5644
5645         if (r_shadow_nummodelshadows)
5646         {
5647                 r_shadow_shadowmapatlas_modelshadows_x = 0;
5648                 r_shadow_shadowmapatlas_modelshadows_y = 0;
5649                 r_shadow_shadowmapatlas_modelshadows_size = size;
5650         }
5651 }
5652
5653 static void R_Shadow_DrawModelShadowMaps(void)
5654 {
5655         int i;
5656         float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
5657         entity_render_t *ent;
5658         vec3_t relativelightorigin;
5659         vec3_t relativelightdirection, relativeforward, relativeright;
5660         vec3_t relativeshadowmins, relativeshadowmaxs;
5661         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
5662         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5663         float m[12];
5664         matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
5665         r_viewport_t viewport;
5666
5667         size = r_shadow_shadowmapatlas_modelshadows_size;
5668         scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size;
5669         radius = 0.5f / scale;
5670         nearclip = -r_shadows_throwdistance.value;
5671         farclip = r_shadows_throwdistance.value;
5672         bias = (r_shadows_shadowmapbias.value < 0) ? r_shadow_shadowmapping_bias.value : r_shadows_shadowmapbias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
5673
5674         // set the parameters that will be used on the regular model renders using these shadows we're about to produce
5675         r_shadow_modelshadowmap_parameters[0] = size;
5676         r_shadow_modelshadowmap_parameters[1] = size;
5677         r_shadow_modelshadowmap_parameters[2] = 1.0;
5678         r_shadow_modelshadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
5679         r_shadow_modelshadowmap_texturescale[0] = 1.0f / r_shadow_shadowmaptexturesize;
5680         r_shadow_modelshadowmap_texturescale[1] = 1.0f / r_shadow_shadowmaptexturesize;
5681         r_shadow_modelshadowmap_texturescale[2] = r_shadow_shadowmapatlas_modelshadows_x;
5682         r_shadow_modelshadowmap_texturescale[3] = r_shadow_shadowmapatlas_modelshadows_y;
5683         r_shadow_usingshadowmaportho = true;
5684
5685         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5686         VectorCopy(prvmshadowdir, shadowdir);
5687         VectorNormalize(shadowdir);
5688         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5689         VectorCopy(prvmshadowfocus, shadowfocus);
5690         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5691         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5692         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5693         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5694         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5695         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5696         if (fabs(dot1) <= fabs(dot2))
5697                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5698         else
5699                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5700         VectorNormalize(shadowforward);
5701         VectorM(scale, shadowforward, &m[0]);
5702         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5703                 dot1 = 1;
5704         m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
5705         CrossProduct(shadowdir, shadowforward, shadowright);
5706         VectorM(scale, shadowright, &m[4]);
5707         m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
5708         VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
5709         m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
5710         Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
5711         Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
5712         R_Viewport_InitOrtho(&viewport, &cameramatrix, r_shadow_shadowmapatlas_modelshadows_x, r_shadow_shadowmapatlas_modelshadows_y, r_shadow_shadowmapatlas_modelshadows_size, r_shadow_shadowmapatlas_modelshadows_size, 0, 0, 1, 1, 0, -1, NULL);
5713         R_SetViewport(&viewport);
5714
5715         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5716
5717         // render into a slightly restricted region so that the borders of the
5718         // shadowmap area fade away, rather than streaking across everything
5719         // outside the usable area
5720         GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
5721
5722         for (i = 0;i < r_shadow_nummodelshadows;i++)
5723         {
5724                 ent = r_shadow_modelshadows[i];
5725                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5726                 Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
5727                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5728                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
5729                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
5730                 relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5731                 relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5732                 relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5733                 relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5734                 relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5735                 relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5736                 RSurf_ActiveModelEntity(ent, false, false, false);
5737                 ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
5738                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5739         }
5740
5741 #if 0
5742         if (r_test.integer)
5743         {
5744                 unsigned char *rawpixels = Z_Malloc(viewport.width*viewport.height*4);
5745                 CHECKGLERROR
5746                 qglReadPixels(viewport.x, viewport.y, viewport.width, viewport.height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, rawpixels);
5747                 CHECKGLERROR
5748                 Image_WriteTGABGRA("r_shadows_2.tga", viewport.width, viewport.height, rawpixels);
5749                 Cvar_SetValueQuick(&r_test, 0);
5750                 Z_Free(rawpixels);
5751         }
5752 #endif
5753
5754         Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5755         Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5756         Matrix4x4_CreateScale3(&scalematrix, size, -size, 1);
5757         Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
5758         Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
5759         Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
5760
5761         switch (vid.renderpath)
5762         {
5763         case RENDERPATH_GL11:
5764         case RENDERPATH_GL13:
5765         case RENDERPATH_GL20:
5766         case RENDERPATH_SOFT:
5767         case RENDERPATH_GLES1:
5768         case RENDERPATH_GLES2:
5769                 break;
5770         case RENDERPATH_D3D9:
5771         case RENDERPATH_D3D10:
5772         case RENDERPATH_D3D11:
5773 #ifdef MATRIX4x4_OPENGLORIENTATION
5774                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5775                 r_shadow_shadowmapmatrix.m[0][1]        *= -1.0f;
5776                 r_shadow_shadowmapmatrix.m[0][2]        *= -1.0f;
5777                 r_shadow_shadowmapmatrix.m[0][3]        *= -1.0f;
5778 #else
5779                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5780                 r_shadow_shadowmapmatrix.m[1][0]        *= -1.0f;
5781                 r_shadow_shadowmapmatrix.m[2][0]        *= -1.0f;
5782                 r_shadow_shadowmapmatrix.m[3][0]        *= -1.0f;
5783 #endif
5784                 break;
5785         }
5786 }
5787
5788 void R_Shadow_DrawModelShadows(void)
5789 {
5790         int i;
5791         float relativethrowdistance;
5792         entity_render_t *ent;
5793         vec3_t relativelightorigin;
5794         vec3_t relativelightdirection;
5795         vec3_t relativeshadowmins, relativeshadowmaxs;
5796         vec3_t tmp, shadowdir;
5797         prvm_vec3_t prvmshadowdir;
5798
5799         if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
5800                 return;
5801
5802         R_ResetViewRendering3D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5803         //GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5804         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5805         R_Shadow_RenderMode_Begin();
5806         R_Shadow_RenderMode_ActiveLight(NULL);
5807         r_shadow_lightscissor[0] = r_refdef.view.x;
5808         r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
5809         r_shadow_lightscissor[2] = r_refdef.view.width;
5810         r_shadow_lightscissor[3] = r_refdef.view.height;
5811         R_Shadow_RenderMode_StencilShadowVolumes(false);
5812
5813         // get shadow dir
5814         if (r_shadows.integer == 2)
5815         {
5816                 Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5817                 VectorCopy(prvmshadowdir, shadowdir);
5818                 VectorNormalize(shadowdir);
5819         }
5820
5821         R_Shadow_ClearStencil();
5822
5823         for (i = 0;i < r_shadow_nummodelshadows;i++)
5824         {
5825                 ent = r_shadow_modelshadows[i];
5826
5827                 // cast shadows from anything of the map (submodels are optional)
5828                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5829                 VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
5830                 VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
5831                 if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
5832                         Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5833                 else
5834                 {
5835                         VectorNegate(ent->render_modellight_lightdir, tmp);
5836                         Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
5837                 }
5838
5839                 VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
5840                 RSurf_ActiveModelEntity(ent, false, false, false);
5841                 ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
5842                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
5843         }
5844
5845         // not really the right mode, but this will disable any silly stencil features
5846         R_Shadow_RenderMode_End();
5847
5848         // set up ortho view for rendering this pass
5849         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5850         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5851         //GL_ScissorTest(true);
5852         //R_EntityMatrix(&identitymatrix);
5853         //R_Mesh_ResetTextureState();
5854         R_ResetViewRendering2D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5855
5856         // set up a darkening blend on shadowed areas
5857         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5858         //GL_DepthRange(0, 1);
5859         //GL_DepthTest(false);
5860         //GL_DepthMask(false);
5861         //GL_PolygonOffset(0, 0);CHECKGLERROR
5862         GL_Color(0, 0, 0, r_shadows_darken.value);
5863         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5864         //GL_DepthFunc(GL_ALWAYS);
5865         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_NOTEQUAL, 128, 255);
5866
5867         // apply the blend to the shadowed areas
5868         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
5869         R_SetupShader_Generic_NoTexture(false, true);
5870         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5871
5872         // restore the viewport
5873         R_SetViewport(&r_refdef.view.viewport);
5874
5875         // restore other state to normal
5876         //R_Shadow_RenderMode_End();
5877 }
5878
5879 static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
5880 {
5881         float zdist;
5882         vec3_t centerorigin;
5883 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5884         float vertex3f[12];
5885 #endif
5886         // if it's too close, skip it
5887         if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
5888                 return;
5889         zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
5890         if (zdist < 32)
5891                 return;
5892         if (usequery && r_numqueries + 2 <= r_maxqueries)
5893         {
5894                 rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
5895                 rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
5896                 // we count potential samples in the middle of the screen, we count actual samples at the light location, this allows counting potential samples of off-screen lights
5897                 VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
5898
5899                 switch(vid.renderpath)
5900                 {
5901                 case RENDERPATH_GL11:
5902                 case RENDERPATH_GL13:
5903                 case RENDERPATH_GL20:
5904                 case RENDERPATH_GLES1:
5905                 case RENDERPATH_GLES2:
5906 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5907                         CHECKGLERROR
5908                         // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
5909                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
5910                         GL_DepthFunc(GL_ALWAYS);
5911                         R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5912                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5913                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5914                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5915                         GL_DepthFunc(GL_LEQUAL);
5916                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
5917                         R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5918                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5919                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5920                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5921                         CHECKGLERROR
5922 #endif
5923                         break;
5924                 case RENDERPATH_D3D9:
5925                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5926                         break;
5927                 case RENDERPATH_D3D10:
5928                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5929                         break;
5930                 case RENDERPATH_D3D11:
5931                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5932                         break;
5933                 case RENDERPATH_SOFT:
5934                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5935                         break;
5936                 }
5937         }
5938         rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
5939 }
5940
5941 static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5942
5943 static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
5944 {
5945         vec3_t color;
5946         unsigned int occlude = 0;
5947         GLint allpixels = 0, visiblepixels = 0;
5948
5949         // now we have to check the query result
5950         if (rtlight->corona_queryindex_visiblepixels)
5951         {
5952                 switch(vid.renderpath)
5953                 {
5954                 case RENDERPATH_GL20:
5955                 case RENDERPATH_GLES1:
5956                 case RENDERPATH_GLES2:
5957 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5958                         // See if we can use the GPU-side method to prevent implicit sync
5959                         if (vid.support.arb_query_buffer_object) {
5960 #define BUFFER_OFFSET(i)    ((GLint *)((unsigned char*)NULL + (i)))
5961                                 if (!r_shadow_occlusion_buf) {
5962                                         qglGenBuffersARB(1, &r_shadow_occlusion_buf);
5963                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5964                                         qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
5965                                 } else {
5966                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5967                                 }
5968                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
5969                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
5970                                 qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
5971                                 occlude = MATERIALFLAG_OCCLUDE;
5972                                 cscale *= rtlight->corona_visibility;
5973                                 CHECKGLERROR
5974                                 break;
5975                         }
5976                         // fallthrough
5977 #else
5978                         return;
5979 #endif
5980                 case RENDERPATH_GL11:
5981                 case RENDERPATH_GL13:
5982 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5983                         CHECKGLERROR
5984                         qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
5985                         qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
5986                         if (visiblepixels < 1 || allpixels < 1)
5987                                 return;
5988                         rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
5989                         cscale *= rtlight->corona_visibility;
5990                         CHECKGLERROR
5991                         break;
5992 #else
5993                         return;
5994 #endif
5995                 case RENDERPATH_D3D9:
5996                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5997                         return;
5998                 case RENDERPATH_D3D10:
5999                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6000                         return;
6001                 case RENDERPATH_D3D11:
6002                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6003                         return;
6004                 case RENDERPATH_SOFT:
6005                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6006                         return;
6007                 default:
6008                         return;
6009                 }
6010         }
6011         else
6012         {
6013                 if (CL_Cache_TraceLineSurfaces(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT).fraction < 1)
6014                         return;
6015         }
6016         VectorScale(rtlight->currentcolor, cscale, color);
6017         if (VectorLength(color) > (1.0f / 256.0f))
6018         {
6019                 float vertex3f[12];
6020                 qboolean negated = (color[0] + color[1] + color[2] < 0) && vid.support.ext_blend_subtract;
6021                 if(negated)
6022                 {
6023                         VectorNegate(color, color);
6024                         GL_BlendEquationSubtract(true);
6025                 }
6026                 R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
6027                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6028                 R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false);
6029                 if(negated)
6030                         GL_BlendEquationSubtract(false);
6031         }
6032 }
6033
6034 void R_Shadow_DrawCoronas(void)
6035 {
6036         int i, flag;
6037         qboolean usequery = false;
6038         size_t lightindex;
6039         dlight_t *light;
6040         rtlight_t *rtlight;
6041         size_t range;
6042         if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
6043                 return;
6044         if (r_fb.water.renderingscene)
6045                 return;
6046         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
6047         R_EntityMatrix(&identitymatrix);
6048
6049         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6050
6051         // check occlusion of coronas
6052         // use GL_ARB_occlusion_query if available
6053         // otherwise use raytraces
6054         r_numqueries = 0;
6055         switch (vid.renderpath)
6056         {
6057         case RENDERPATH_GL11:
6058         case RENDERPATH_GL13:
6059         case RENDERPATH_GL20:
6060         case RENDERPATH_GLES1:
6061         case RENDERPATH_GLES2:
6062                 usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
6063 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
6064                 if (usequery)
6065                 {
6066                         GL_ColorMask(0,0,0,0);
6067                         if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
6068                         if (r_maxqueries < MAX_OCCLUSION_QUERIES)
6069                         {
6070                                 i = r_maxqueries;
6071                                 r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
6072                                 r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
6073                                 CHECKGLERROR
6074                                 qglGenQueriesARB(r_maxqueries - i, r_queries + i);
6075                                 CHECKGLERROR
6076                         }
6077                         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
6078                         GL_BlendFunc(GL_ONE, GL_ZERO);
6079                         GL_CullFace(GL_NONE);
6080                         GL_DepthMask(false);
6081                         GL_DepthRange(0, 1);
6082                         GL_PolygonOffset(0, 0);
6083                         GL_DepthTest(true);
6084                         R_Mesh_ResetTextureState();
6085                         R_SetupShader_Generic_NoTexture(false, false);
6086                 }
6087 #endif
6088                 break;
6089         case RENDERPATH_D3D9:
6090                 usequery = false;
6091                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6092                 break;
6093         case RENDERPATH_D3D10:
6094                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6095                 break;
6096         case RENDERPATH_D3D11:
6097                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6098                 break;
6099         case RENDERPATH_SOFT:
6100                 usequery = false;
6101                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6102                 break;
6103         }
6104         for (lightindex = 0;lightindex < range;lightindex++)
6105         {
6106                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6107                 if (!light)
6108                         continue;
6109                 rtlight = &light->rtlight;
6110                 rtlight->corona_visibility = 0;
6111                 rtlight->corona_queryindex_visiblepixels = 0;
6112                 rtlight->corona_queryindex_allpixels = 0;
6113                 if (!(rtlight->flags & flag))
6114                         continue;
6115                 if (rtlight->corona <= 0)
6116                         continue;
6117                 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex)
6118                         continue;
6119                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
6120         }
6121         for (i = 0;i < r_refdef.scene.numlights;i++)
6122         {
6123                 rtlight = r_refdef.scene.lights[i];
6124                 rtlight->corona_visibility = 0;
6125                 rtlight->corona_queryindex_visiblepixels = 0;
6126                 rtlight->corona_queryindex_allpixels = 0;
6127                 if (!(rtlight->flags & flag))
6128                         continue;
6129                 if (rtlight->corona <= 0)
6130                         continue;
6131                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
6132         }
6133         if (usequery)
6134                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6135
6136         // now draw the coronas using the query data for intensity info
6137         for (lightindex = 0;lightindex < range;lightindex++)
6138         {
6139                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6140                 if (!light)
6141                         continue;
6142                 rtlight = &light->rtlight;
6143                 if (rtlight->corona_visibility <= 0)
6144                         continue;
6145                 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
6146         }
6147         for (i = 0;i < r_refdef.scene.numlights;i++)
6148         {
6149                 rtlight = r_refdef.scene.lights[i];
6150                 if (rtlight->corona_visibility <= 0)
6151                         continue;
6152                 if (gl_flashblend.integer)
6153                         R_DrawCorona(rtlight, rtlight->corona, rtlight->radius * rtlight->coronasizescale * 2.0f);
6154                 else
6155                         R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
6156         }
6157 }
6158
6159
6160
6161 static dlight_t *R_Shadow_NewWorldLight(void)
6162 {
6163         return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
6164 }
6165
6166 static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
6167 {
6168         matrix4x4_t matrix;
6169
6170         // note that style is no longer validated here, -1 is used for unstyled lights and >= MAX_LIGHTSTYLES is accepted for sake of editing rtlights files that might be out of bounds but perfectly formatted
6171
6172         // validate parameters
6173         if (!cubemapname)
6174                 cubemapname = "";
6175
6176         // copy to light properties
6177         VectorCopy(origin, light->origin);
6178         light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
6179         light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
6180         light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
6181         /*
6182         light->color[0] = max(color[0], 0);
6183         light->color[1] = max(color[1], 0);
6184         light->color[2] = max(color[2], 0);
6185         */
6186         light->color[0] = color[0];
6187         light->color[1] = color[1];
6188         light->color[2] = color[2];
6189         light->radius = max(radius, 0);
6190         light->style = style;
6191         light->shadow = shadowenable;
6192         light->corona = corona;
6193         strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
6194         light->coronasizescale = coronasizescale;
6195         light->ambientscale = ambientscale;
6196         light->diffusescale = diffusescale;
6197         light->specularscale = specularscale;
6198         light->flags = flags;
6199
6200         // update renderable light data
6201         Matrix4x4_CreateFromQuakeEntity(&matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], light->radius);
6202         R_RTLight_Update(&light->rtlight, true, &matrix, light->color, light->style, light->cubemapname[0] ? light->cubemapname : NULL, light->shadow, light->corona, light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
6203 }
6204
6205 static void R_Shadow_FreeWorldLight(dlight_t *light)
6206 {
6207         if (r_shadow_selectedlight == light)
6208                 r_shadow_selectedlight = NULL;
6209         R_RTLight_Uncompile(&light->rtlight);
6210         Mem_ExpandableArray_FreeRecord(&r_shadow_worldlightsarray, light);
6211 }
6212
6213 void R_Shadow_ClearWorldLights(void)
6214 {
6215         size_t lightindex;
6216         dlight_t *light;
6217         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6218         for (lightindex = 0;lightindex < range;lightindex++)
6219         {
6220                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6221                 if (light)
6222                         R_Shadow_FreeWorldLight(light);
6223         }
6224         r_shadow_selectedlight = NULL;
6225 }
6226
6227 static void R_Shadow_SelectLight(dlight_t *light)
6228 {
6229         if (r_shadow_selectedlight)
6230                 r_shadow_selectedlight->selected = false;
6231         r_shadow_selectedlight = light;
6232         if (r_shadow_selectedlight)
6233                 r_shadow_selectedlight->selected = true;
6234 }
6235
6236 static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6237 {
6238         // this is never batched (there can be only one)
6239         float vertex3f[12];
6240         R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
6241         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6242         R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6243 }
6244
6245 static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6246 {
6247         float intensity;
6248         float s;
6249         vec3_t spritecolor;
6250         skinframe_t *skinframe;
6251         float vertex3f[12];
6252
6253         // this is never batched (due to the ent parameter changing every time)
6254         // so numsurfaces == 1 and surfacelist[0] == lightnumber
6255         const dlight_t *light = (dlight_t *)ent;
6256         s = EDLIGHTSPRSIZE;
6257
6258         R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
6259
6260         intensity = 0.5f;
6261         VectorScale(light->color, intensity, spritecolor);
6262         if (VectorLength(spritecolor) < 0.1732f)
6263                 VectorSet(spritecolor, 0.1f, 0.1f, 0.1f);
6264         if (VectorLength(spritecolor) > 1.0f)
6265                 VectorNormalize(spritecolor);
6266
6267         // draw light sprite
6268         if (light->cubemapname[0] && !light->shadow)
6269                 skinframe = r_editlights_sprcubemapnoshadowlight;
6270         else if (light->cubemapname[0])
6271                 skinframe = r_editlights_sprcubemaplight;
6272         else if (!light->shadow)
6273                 skinframe = r_editlights_sprnoshadowlight;
6274         else
6275                 skinframe = r_editlights_sprlight;
6276
6277         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, spritecolor[0], spritecolor[1], spritecolor[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6278         R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6279
6280         // draw selection sprite if light is selected
6281         if (light->selected)
6282         {
6283                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6284                 R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6285                 // VorteX todo: add normalmode/realtime mode light overlay sprites?
6286         }
6287 }
6288
6289 void R_Shadow_DrawLightSprites(void)
6290 {
6291         size_t lightindex;
6292         dlight_t *light;
6293         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6294         for (lightindex = 0;lightindex < range;lightindex++)
6295         {
6296                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6297                 if (light)
6298                         R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
6299         }
6300         if (!r_editlights_lockcursor)
6301                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
6302 }
6303
6304 int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
6305 {
6306         unsigned int range;
6307         dlight_t *light;
6308         rtlight_t *rtlight;
6309         range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
6310         if (lightindex >= range)
6311                 return -1;
6312         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6313         if (!light)
6314                 return 0;
6315         rtlight = &light->rtlight;
6316         //if (!(rtlight->flags & flag))
6317         //      return 0;
6318         VectorCopy(rtlight->shadoworigin, origin);
6319         *radius = rtlight->radius;
6320         VectorCopy(rtlight->color, color);
6321         return 1;
6322 }
6323
6324 static void R_Shadow_SelectLightInView(void)
6325 {
6326         float bestrating, rating, temp[3];
6327         dlight_t *best;
6328         size_t lightindex;
6329         dlight_t *light;
6330         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6331         best = NULL;
6332         bestrating = 0;
6333
6334         if (r_editlights_lockcursor)
6335                 return;
6336         for (lightindex = 0;lightindex < range;lightindex++)
6337         {
6338                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6339                 if (!light)
6340                         continue;
6341                 VectorSubtract(light->origin, r_refdef.view.origin, temp);
6342                 rating = (DotProduct(temp, r_refdef.view.forward) / sqrt(DotProduct(temp, temp)));
6343                 if (rating >= 0.95)
6344                 {
6345                         rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
6346                         if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f)
6347                         {
6348                                 bestrating = rating;
6349                                 best = light;
6350                         }
6351                 }
6352         }
6353         R_Shadow_SelectLight(best);
6354 }
6355
6356 void R_Shadow_LoadWorldLights(void)
6357 {
6358         int n, a, style, shadow, flags;
6359         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
6360         float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
6361         if (cl.worldmodel == NULL)
6362         {
6363                 Con_Print("No map loaded.\n");
6364                 return;
6365         }
6366         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6367         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6368         if (lightsstring)
6369         {
6370                 s = lightsstring;
6371                 n = 0;
6372                 while (*s)
6373                 {
6374                         /*
6375                         t = s;
6376                         shadow = true;
6377                         for (;COM_Parse(t, true) && strcmp(
6378                         if (COM_Parse(t, true))
6379                         {
6380                                 if (com_token[0] == '!')
6381                                 {
6382                                         shadow = false;
6383                                         origin[0] = atof(com_token+1);
6384                                 }
6385                                 else
6386                                         origin[0] = atof(com_token);
6387                                 if (Com_Parse(t
6388                         }
6389                         */
6390                         t = s;
6391                         while (*s && *s != '\n' && *s != '\r')
6392                                 s++;
6393                         if (!*s)
6394                                 break;
6395                         tempchar = *s;
6396                         shadow = true;
6397                         // check for modifier flags
6398                         if (*t == '!')
6399                         {
6400                                 shadow = false;
6401                                 t++;
6402                         }
6403                         *s = 0;
6404 #if _MSC_VER >= 1400
6405 #define sscanf sscanf_s
6406 #endif
6407                         cubemapname[sizeof(cubemapname)-1] = 0;
6408 #if MAX_QPATH != 128
6409 #error update this code if MAX_QPATH changes
6410 #endif
6411                         a = sscanf(t, "%f %f %f %f %f %f %f %d %127s %f %f %f %f %f %f %f %f %i", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname
6412 #if _MSC_VER >= 1400
6413 , sizeof(cubemapname)
6414 #endif
6415 , &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
6416                         *s = tempchar;
6417                         if (a < 18)
6418                                 flags = LIGHTFLAG_REALTIMEMODE;
6419                         if (a < 17)
6420                                 specularscale = 1;
6421                         if (a < 16)
6422                                 diffusescale = 1;
6423                         if (a < 15)
6424                                 ambientscale = 0;
6425                         if (a < 14)
6426                                 coronasizescale = 0.25f;
6427                         if (a < 13)
6428                                 VectorClear(angles);
6429                         if (a < 10)
6430                                 corona = 0;
6431                         if (a < 9 || !strcmp(cubemapname, "\"\""))
6432                                 cubemapname[0] = 0;
6433                         // remove quotes on cubemapname
6434                         if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
6435                         {
6436                                 size_t namelen;
6437                                 namelen = strlen(cubemapname) - 2;
6438                                 memmove(cubemapname, cubemapname + 1, namelen);
6439                                 cubemapname[namelen] = '\0';
6440                         }
6441                         if (a < 8)
6442                         {
6443                                 Con_Printf("found %d parameters on line %i, should be 8 or more parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style \"cubemapname\" corona angles[0] angles[1] angles[2] coronasizescale ambientscale diffusescale specularscale flags)\n", a, n + 1);
6444                                 break;
6445                         }
6446                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
6447                         if (*s == '\r')
6448                                 s++;
6449                         if (*s == '\n')
6450                                 s++;
6451                         n++;
6452                 }
6453                 if (*s)
6454                         Con_Printf("invalid rtlights file \"%s\"\n", name);
6455                 Mem_Free(lightsstring);
6456         }
6457 }
6458
6459 void R_Shadow_SaveWorldLights(void)
6460 {
6461         size_t lightindex;
6462         dlight_t *light;
6463         size_t bufchars, bufmaxchars;
6464         char *buf, *oldbuf;
6465         char name[MAX_QPATH];
6466         char line[MAX_INPUTLINE];
6467         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
6468         // I hate lines which are 3 times my screen size :( --blub
6469         if (!range)
6470                 return;
6471         if (cl.worldmodel == NULL)
6472         {
6473                 Con_Print("No map loaded.\n");
6474                 return;
6475         }
6476         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6477         bufchars = bufmaxchars = 0;
6478         buf = NULL;
6479         for (lightindex = 0;lightindex < range;lightindex++)
6480         {
6481                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6482                 if (!light)
6483                         continue;
6484                 if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE)
6485                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f %f %f %f %f %i\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2], light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
6486                 else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
6487                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2]);
6488                 else
6489                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style);
6490                 if (bufchars + strlen(line) > bufmaxchars)
6491                 {
6492                         bufmaxchars = bufchars + strlen(line) + 2048;
6493                         oldbuf = buf;
6494                         buf = (char *)Mem_Alloc(tempmempool, bufmaxchars);
6495                         if (oldbuf)
6496                         {
6497                                 if (bufchars)
6498                                         memcpy(buf, oldbuf, bufchars);
6499                                 Mem_Free(oldbuf);
6500                         }
6501                 }
6502                 if (strlen(line))
6503                 {
6504                         memcpy(buf + bufchars, line, strlen(line));
6505                         bufchars += strlen(line);
6506                 }
6507         }
6508         if (bufchars)
6509                 FS_WriteFile(name, buf, (fs_offset_t)bufchars);
6510         if (buf)
6511                 Mem_Free(buf);
6512 }
6513
6514 void R_Shadow_LoadLightsFile(void)
6515 {
6516         int n, a, style;
6517         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
6518         float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
6519         if (cl.worldmodel == NULL)
6520         {
6521                 Con_Print("No map loaded.\n");
6522                 return;
6523         }
6524         dpsnprintf(name, sizeof(name), "%s.lights", cl.worldnamenoextension);
6525         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6526         if (lightsstring)
6527         {
6528                 s = lightsstring;
6529                 n = 0;
6530                 while (*s)
6531                 {
6532                         t = s;
6533                         while (*s && *s != '\n' && *s != '\r')
6534                                 s++;
6535                         if (!*s)
6536                                 break;
6537                         tempchar = *s;
6538                         *s = 0;
6539                         a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &origin[0], &origin[1], &origin[2], &falloff, &color[0], &color[1], &color[2], &subtract, &spotdir[0], &spotdir[1], &spotdir[2], &spotcone, &distbias, &style);
6540                         *s = tempchar;
6541                         if (a < 14)
6542                         {
6543                                 Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
6544                                 break;
6545                         }
6546                         radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f));
6547                         radius = bound(15, radius, 4096);
6548                         VectorScale(color, (2.0f / (8388608.0f)), color);
6549                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6550                         if (*s == '\r')
6551                                 s++;
6552                         if (*s == '\n')
6553                                 s++;
6554                         n++;
6555                 }
6556                 if (*s)
6557                         Con_Printf("invalid lights file \"%s\"\n", name);
6558                 Mem_Free(lightsstring);
6559         }
6560 }
6561
6562 // tyrlite/hmap2 light types in the delay field
6563 typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
6564
6565 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
6566 {
6567         int entnum;
6568         int style;
6569         int islight;
6570         int skin;
6571         int pflags;
6572         //int effects;
6573         int type;
6574         int n;
6575         char *entfiledata;
6576         const char *data;
6577         float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
6578         char key[256], value[MAX_INPUTLINE];
6579         char vabuf[1024];
6580
6581         if (cl.worldmodel == NULL)
6582         {
6583                 Con_Print("No map loaded.\n");
6584                 return;
6585         }
6586         // try to load a .ent file first
6587         dpsnprintf(key, sizeof(key), "%s.ent", cl.worldnamenoextension);
6588         data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL);
6589         // and if that is not found, fall back to the bsp file entity string
6590         if (!data)
6591                 data = cl.worldmodel->brush.entities;
6592         if (!data)
6593                 return;
6594         for (entnum = 0;COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{';entnum++)
6595         {
6596                 type = LIGHTTYPE_MINUSX;
6597                 origin[0] = origin[1] = origin[2] = 0;
6598                 originhack[0] = originhack[1] = originhack[2] = 0;
6599                 angles[0] = angles[1] = angles[2] = 0;
6600                 color[0] = color[1] = color[2] = 1;
6601                 light[0] = light[1] = light[2] = 1;light[3] = 300;
6602                 overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
6603                 fadescale = 1;
6604                 lightscale = 1;
6605                 style = 0;
6606                 skin = 0;
6607                 pflags = 0;
6608                 //effects = 0;
6609                 islight = false;
6610                 while (1)
6611                 {
6612                         if (!COM_ParseToken_Simple(&data, false, false, true))
6613                                 break; // error
6614                         if (com_token[0] == '}')
6615                                 break; // end of entity
6616                         if (com_token[0] == '_')
6617                                 strlcpy(key, com_token + 1, sizeof(key));
6618                         else
6619                                 strlcpy(key, com_token, sizeof(key));
6620                         while (key[strlen(key)-1] == ' ') // remove trailing spaces
6621                                 key[strlen(key)-1] = 0;
6622                         if (!COM_ParseToken_Simple(&data, false, false, true))
6623                                 break; // error
6624                         strlcpy(value, com_token, sizeof(value));
6625
6626                         // now that we have the key pair worked out...
6627                         if (!strcmp("light", key))
6628                         {
6629                                 n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
6630                                 if (n == 1)
6631                                 {
6632                                         // quake
6633                                         light[0] = vec[0] * (1.0f / 256.0f);
6634                                         light[1] = vec[0] * (1.0f / 256.0f);
6635                                         light[2] = vec[0] * (1.0f / 256.0f);
6636                                         light[3] = vec[0];
6637                                 }
6638                                 else if (n == 4)
6639                                 {
6640                                         // halflife
6641                                         light[0] = vec[0] * (1.0f / 255.0f);
6642                                         light[1] = vec[1] * (1.0f / 255.0f);
6643                                         light[2] = vec[2] * (1.0f / 255.0f);
6644                                         light[3] = vec[3];
6645                                 }
6646                         }
6647                         else if (!strcmp("delay", key))
6648                                 type = atoi(value);
6649                         else if (!strcmp("origin", key))
6650                                 sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
6651                         else if (!strcmp("angle", key))
6652                                 angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
6653                         else if (!strcmp("angles", key))
6654                                 sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
6655                         else if (!strcmp("color", key))
6656                                 sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
6657                         else if (!strcmp("wait", key))
6658                                 fadescale = atof(value);
6659                         else if (!strcmp("classname", key))
6660                         {
6661                                 if (!strncmp(value, "light", 5))
6662                                 {
6663                                         islight = true;
6664                                         if (!strcmp(value, "light_fluoro"))
6665                                         {
6666                                                 originhack[0] = 0;
6667                                                 originhack[1] = 0;
6668                                                 originhack[2] = 0;
6669                                                 overridecolor[0] = 1;
6670                                                 overridecolor[1] = 1;
6671                                                 overridecolor[2] = 1;
6672                                         }
6673                                         if (!strcmp(value, "light_fluorospark"))
6674                                         {
6675                                                 originhack[0] = 0;
6676                                                 originhack[1] = 0;
6677                                                 originhack[2] = 0;
6678                                                 overridecolor[0] = 1;
6679                                                 overridecolor[1] = 1;
6680                                                 overridecolor[2] = 1;
6681                                         }
6682                                         if (!strcmp(value, "light_globe"))
6683                                         {
6684                                                 originhack[0] = 0;
6685                                                 originhack[1] = 0;
6686                                                 originhack[2] = 0;
6687                                                 overridecolor[0] = 1;
6688                                                 overridecolor[1] = 0.8;
6689                                                 overridecolor[2] = 0.4;
6690                                         }
6691                                         if (!strcmp(value, "light_flame_large_yellow"))
6692                                         {
6693                                                 originhack[0] = 0;
6694                                                 originhack[1] = 0;
6695                                                 originhack[2] = 0;
6696                                                 overridecolor[0] = 1;
6697                                                 overridecolor[1] = 0.5;
6698                                                 overridecolor[2] = 0.1;
6699                                         }
6700                                         if (!strcmp(value, "light_flame_small_yellow"))
6701                                         {
6702                                                 originhack[0] = 0;
6703                                                 originhack[1] = 0;
6704                                                 originhack[2] = 0;
6705                                                 overridecolor[0] = 1;
6706                                                 overridecolor[1] = 0.5;
6707                                                 overridecolor[2] = 0.1;
6708                                         }
6709                                         if (!strcmp(value, "light_torch_small_white"))
6710                                         {
6711                                                 originhack[0] = 0;
6712                                                 originhack[1] = 0;
6713                                                 originhack[2] = 0;
6714                                                 overridecolor[0] = 1;
6715                                                 overridecolor[1] = 0.5;
6716                                                 overridecolor[2] = 0.1;
6717                                         }
6718                                         if (!strcmp(value, "light_torch_small_walltorch"))
6719                                         {
6720                                                 originhack[0] = 0;
6721                                                 originhack[1] = 0;
6722                                                 originhack[2] = 0;
6723                                                 overridecolor[0] = 1;
6724                                                 overridecolor[1] = 0.5;
6725                                                 overridecolor[2] = 0.1;
6726                                         }
6727                                 }
6728                         }
6729                         else if (!strcmp("style", key))
6730                                 style = atoi(value);
6731                         else if (!strcmp("skin", key))
6732                                 skin = (int)atof(value);
6733                         else if (!strcmp("pflags", key))
6734                                 pflags = (int)atof(value);
6735                         //else if (!strcmp("effects", key))
6736                         //      effects = (int)atof(value);
6737                         else if (cl.worldmodel->type == mod_brushq3)
6738                         {
6739                                 if (!strcmp("scale", key))
6740                                         lightscale = atof(value);
6741                                 if (!strcmp("fade", key))
6742                                         fadescale = atof(value);
6743                         }
6744                 }
6745                 if (!islight)
6746                         continue;
6747                 if (lightscale <= 0)
6748                         lightscale = 1;
6749                 if (fadescale <= 0)
6750                         fadescale = 1;
6751                 if (color[0] == color[1] && color[0] == color[2])
6752                 {
6753                         color[0] *= overridecolor[0];
6754                         color[1] *= overridecolor[1];
6755                         color[2] *= overridecolor[2];
6756                 }
6757                 radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
6758                 color[0] = color[0] * light[0];
6759                 color[1] = color[1] * light[1];
6760                 color[2] = color[2] * light[2];
6761                 switch (type)
6762                 {
6763                 case LIGHTTYPE_MINUSX:
6764                         break;
6765                 case LIGHTTYPE_RECIPX:
6766                         radius *= 2;
6767                         VectorScale(color, (1.0f / 16.0f), color);
6768                         break;
6769                 case LIGHTTYPE_RECIPXX:
6770                         radius *= 2;
6771                         VectorScale(color, (1.0f / 16.0f), color);
6772                         break;
6773                 default:
6774                 case LIGHTTYPE_NONE:
6775                         break;
6776                 case LIGHTTYPE_SUN:
6777                         break;
6778                 case LIGHTTYPE_MINUSXX:
6779                         break;
6780                 }
6781                 VectorAdd(origin, originhack, origin);
6782                 if (radius >= 1)
6783                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6784         }
6785         if (entfiledata)
6786                 Mem_Free(entfiledata);
6787 }
6788
6789
6790 static void R_Shadow_SetCursorLocationForView(void)
6791 {
6792         vec_t dist, push;
6793         vec3_t dest, endpos;
6794         trace_t trace;
6795         VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
6796         trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true);
6797         if (trace.fraction < 1)
6798         {
6799                 dist = trace.fraction * r_editlights_cursordistance.value;
6800                 push = r_editlights_cursorpushback.value;
6801                 if (push > dist)
6802                         push = dist;
6803                 push = -push;
6804                 VectorMA(trace.endpos, push, r_refdef.view.forward, endpos);
6805                 VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
6806         }
6807         else
6808         {
6809                 VectorClear( endpos );
6810         }
6811         r_editlights_cursorlocation[0] = floor(endpos[0] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6812         r_editlights_cursorlocation[1] = floor(endpos[1] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6813         r_editlights_cursorlocation[2] = floor(endpos[2] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6814 }
6815
6816 void R_Shadow_UpdateWorldLightSelection(void)
6817 {
6818         if (r_editlights.integer)
6819         {
6820                 R_Shadow_SetCursorLocationForView();
6821                 R_Shadow_SelectLightInView();
6822         }
6823         else
6824                 R_Shadow_SelectLight(NULL);
6825 }
6826
6827 static void R_Shadow_EditLights_Clear_f(void)
6828 {
6829         R_Shadow_ClearWorldLights();
6830 }
6831
6832 void R_Shadow_EditLights_Reload_f(void)
6833 {
6834         if (!cl.worldmodel)
6835                 return;
6836         strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname));
6837         R_Shadow_ClearWorldLights();
6838         if (r_shadow_realtime_world_importlightentitiesfrommap.integer <= 1)
6839         {
6840                 R_Shadow_LoadWorldLights();
6841                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6842                         R_Shadow_LoadLightsFile();
6843         }
6844         if (r_shadow_realtime_world_importlightentitiesfrommap.integer >= 1)
6845         {
6846                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6847                         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6848         }
6849 }
6850
6851 static void R_Shadow_EditLights_Save_f(void)
6852 {
6853         if (!cl.worldmodel)
6854                 return;
6855         R_Shadow_SaveWorldLights();
6856 }
6857
6858 static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
6859 {
6860         R_Shadow_ClearWorldLights();
6861         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6862 }
6863
6864 static void R_Shadow_EditLights_ImportLightsFile_f(void)
6865 {
6866         R_Shadow_ClearWorldLights();
6867         R_Shadow_LoadLightsFile();
6868 }
6869
6870 static void R_Shadow_EditLights_Spawn_f(void)
6871 {
6872         vec3_t color;
6873         if (!r_editlights.integer)
6874         {
6875                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6876                 return;
6877         }
6878         if (Cmd_Argc() != 1)
6879         {
6880                 Con_Print("r_editlights_spawn does not take parameters\n");
6881                 return;
6882         }
6883         color[0] = color[1] = color[2] = 1;
6884         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6885 }
6886
6887 static void R_Shadow_EditLights_Edit_f(void)
6888 {
6889         vec3_t origin, angles, color;
6890         vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
6891         int style, shadows, flags, normalmode, realtimemode;
6892         char cubemapname[MAX_INPUTLINE];
6893         if (!r_editlights.integer)
6894         {
6895                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6896                 return;
6897         }
6898         if (!r_shadow_selectedlight)
6899         {
6900                 Con_Print("No selected light.\n");
6901                 return;
6902         }
6903         VectorCopy(r_shadow_selectedlight->origin, origin);
6904         VectorCopy(r_shadow_selectedlight->angles, angles);
6905         VectorCopy(r_shadow_selectedlight->color, color);
6906         radius = r_shadow_selectedlight->radius;
6907         style = r_shadow_selectedlight->style;
6908         if (r_shadow_selectedlight->cubemapname)
6909                 strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
6910         else
6911                 cubemapname[0] = 0;
6912         shadows = r_shadow_selectedlight->shadow;
6913         corona = r_shadow_selectedlight->corona;
6914         coronasizescale = r_shadow_selectedlight->coronasizescale;
6915         ambientscale = r_shadow_selectedlight->ambientscale;
6916         diffusescale = r_shadow_selectedlight->diffusescale;
6917         specularscale = r_shadow_selectedlight->specularscale;
6918         flags = r_shadow_selectedlight->flags;
6919         normalmode = (flags & LIGHTFLAG_NORMALMODE) != 0;
6920         realtimemode = (flags & LIGHTFLAG_REALTIMEMODE) != 0;
6921         if (!strcmp(Cmd_Argv(1), "origin"))
6922         {
6923                 if (Cmd_Argc() != 5)
6924                 {
6925                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6926                         return;
6927                 }
6928                 origin[0] = atof(Cmd_Argv(2));
6929                 origin[1] = atof(Cmd_Argv(3));
6930                 origin[2] = atof(Cmd_Argv(4));
6931         }
6932         else if (!strcmp(Cmd_Argv(1), "originscale"))
6933         {
6934                 if (Cmd_Argc() != 5)
6935                 {
6936                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6937                         return;
6938                 }
6939                 origin[0] *= atof(Cmd_Argv(2));
6940                 origin[1] *= atof(Cmd_Argv(3));
6941                 origin[2] *= atof(Cmd_Argv(4));
6942         }
6943         else if (!strcmp(Cmd_Argv(1), "originx"))
6944         {
6945                 if (Cmd_Argc() != 3)
6946                 {
6947                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6948                         return;
6949                 }
6950                 origin[0] = atof(Cmd_Argv(2));
6951         }
6952         else if (!strcmp(Cmd_Argv(1), "originy"))
6953         {
6954                 if (Cmd_Argc() != 3)
6955                 {
6956                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6957                         return;
6958                 }
6959                 origin[1] = atof(Cmd_Argv(2));
6960         }
6961         else if (!strcmp(Cmd_Argv(1), "originz"))
6962         {
6963                 if (Cmd_Argc() != 3)
6964                 {
6965                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6966                         return;
6967                 }
6968                 origin[2] = atof(Cmd_Argv(2));
6969         }
6970         else if (!strcmp(Cmd_Argv(1), "move"))
6971         {
6972                 if (Cmd_Argc() != 5)
6973                 {
6974                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6975                         return;
6976                 }
6977                 origin[0] += atof(Cmd_Argv(2));
6978                 origin[1] += atof(Cmd_Argv(3));
6979                 origin[2] += atof(Cmd_Argv(4));
6980         }
6981         else if (!strcmp(Cmd_Argv(1), "movex"))
6982         {
6983                 if (Cmd_Argc() != 3)
6984                 {
6985                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6986                         return;
6987                 }
6988                 origin[0] += atof(Cmd_Argv(2));
6989         }
6990         else if (!strcmp(Cmd_Argv(1), "movey"))
6991         {
6992                 if (Cmd_Argc() != 3)
6993                 {
6994                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6995                         return;
6996                 }
6997                 origin[1] += atof(Cmd_Argv(2));
6998         }
6999         else if (!strcmp(Cmd_Argv(1), "movez"))
7000         {
7001                 if (Cmd_Argc() != 3)
7002                 {
7003                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7004                         return;
7005                 }
7006                 origin[2] += atof(Cmd_Argv(2));
7007         }
7008         else if (!strcmp(Cmd_Argv(1), "angles"))
7009         {
7010                 if (Cmd_Argc() != 5)
7011                 {
7012                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
7013                         return;
7014                 }
7015                 angles[0] = atof(Cmd_Argv(2));
7016                 angles[1] = atof(Cmd_Argv(3));
7017                 angles[2] = atof(Cmd_Argv(4));
7018         }
7019         else if (!strcmp(Cmd_Argv(1), "anglesx"))
7020         {
7021                 if (Cmd_Argc() != 3)
7022                 {
7023                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7024                         return;
7025                 }
7026                 angles[0] = atof(Cmd_Argv(2));
7027         }
7028         else if (!strcmp(Cmd_Argv(1), "anglesy"))
7029         {
7030                 if (Cmd_Argc() != 3)
7031                 {
7032                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7033                         return;
7034                 }
7035                 angles[1] = atof(Cmd_Argv(2));
7036         }
7037         else if (!strcmp(Cmd_Argv(1), "anglesz"))
7038         {
7039                 if (Cmd_Argc() != 3)
7040                 {
7041                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7042                         return;
7043                 }
7044                 angles[2] = atof(Cmd_Argv(2));
7045         }
7046         else if (!strcmp(Cmd_Argv(1), "color"))
7047         {
7048                 if (Cmd_Argc() != 5)
7049                 {
7050                         Con_Printf("usage: r_editlights_edit %s red green blue\n", Cmd_Argv(1));
7051                         return;
7052                 }
7053                 color[0] = atof(Cmd_Argv(2));
7054                 color[1] = atof(Cmd_Argv(3));
7055                 color[2] = atof(Cmd_Argv(4));
7056         }
7057         else if (!strcmp(Cmd_Argv(1), "radius"))
7058         {
7059                 if (Cmd_Argc() != 3)
7060                 {
7061                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7062                         return;
7063                 }
7064                 radius = atof(Cmd_Argv(2));
7065         }
7066         else if (!strcmp(Cmd_Argv(1), "colorscale"))
7067         {
7068                 if (Cmd_Argc() == 3)
7069                 {
7070                         double scale = atof(Cmd_Argv(2));
7071                         color[0] *= scale;
7072                         color[1] *= scale;
7073                         color[2] *= scale;
7074                 }
7075                 else
7076                 {
7077                         if (Cmd_Argc() != 5)
7078                         {
7079                                 Con_Printf("usage: r_editlights_edit %s red green blue  (OR grey instead of red green blue)\n", Cmd_Argv(1));
7080                                 return;
7081                         }
7082                         color[0] *= atof(Cmd_Argv(2));
7083                         color[1] *= atof(Cmd_Argv(3));
7084                         color[2] *= atof(Cmd_Argv(4));
7085                 }
7086         }
7087         else if (!strcmp(Cmd_Argv(1), "radiusscale") || !strcmp(Cmd_Argv(1), "sizescale"))
7088         {
7089                 if (Cmd_Argc() != 3)
7090                 {
7091                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7092                         return;
7093                 }
7094                 radius *= atof(Cmd_Argv(2));
7095         }
7096         else if (!strcmp(Cmd_Argv(1), "style"))
7097         {
7098                 if (Cmd_Argc() != 3)
7099                 {
7100                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7101                         return;
7102                 }
7103                 style = atoi(Cmd_Argv(2));
7104         }
7105         else if (!strcmp(Cmd_Argv(1), "cubemap"))
7106         {
7107                 if (Cmd_Argc() > 3)
7108                 {
7109                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7110                         return;
7111                 }
7112                 if (Cmd_Argc() == 3)
7113                         strlcpy(cubemapname, Cmd_Argv(2), sizeof(cubemapname));
7114                 else
7115                         cubemapname[0] = 0;
7116         }
7117         else if (!strcmp(Cmd_Argv(1), "shadows"))
7118         {
7119                 if (Cmd_Argc() != 3)
7120                 {
7121                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7122                         return;
7123                 }
7124                 shadows = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
7125         }
7126         else if (!strcmp(Cmd_Argv(1), "corona"))
7127         {
7128                 if (Cmd_Argc() != 3)
7129                 {
7130                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7131                         return;
7132                 }
7133                 corona = atof(Cmd_Argv(2));
7134         }
7135         else if (!strcmp(Cmd_Argv(1), "coronasize"))
7136         {
7137                 if (Cmd_Argc() != 3)
7138                 {
7139                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7140                         return;
7141                 }
7142                 coronasizescale = atof(Cmd_Argv(2));
7143         }
7144         else if (!strcmp(Cmd_Argv(1), "ambient"))
7145         {
7146                 if (Cmd_Argc() != 3)
7147                 {
7148                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7149                         return;
7150                 }
7151                 ambientscale = atof(Cmd_Argv(2));
7152         }
7153         else if (!strcmp(Cmd_Argv(1), "diffuse"))
7154         {
7155                 if (Cmd_Argc() != 3)
7156                 {
7157                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7158                         return;
7159                 }
7160                 diffusescale = atof(Cmd_Argv(2));
7161         }
7162         else if (!strcmp(Cmd_Argv(1), "specular"))
7163         {
7164                 if (Cmd_Argc() != 3)
7165                 {
7166                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7167                         return;
7168                 }
7169                 specularscale = atof(Cmd_Argv(2));
7170         }
7171         else if (!strcmp(Cmd_Argv(1), "normalmode"))
7172         {
7173                 if (Cmd_Argc() != 3)
7174                 {
7175                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7176                         return;
7177                 }
7178                 normalmode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
7179         }
7180         else if (!strcmp(Cmd_Argv(1), "realtimemode"))
7181         {
7182                 if (Cmd_Argc() != 3)
7183                 {
7184                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7185                         return;
7186                 }
7187                 realtimemode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
7188         }
7189         else
7190         {
7191                 Con_Print("usage: r_editlights_edit [property] [value]\n");
7192                 Con_Print("Selected light's properties:\n");
7193                 Con_Printf("Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
7194                 Con_Printf("Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
7195                 Con_Printf("Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
7196                 Con_Printf("Radius       : %f\n", r_shadow_selectedlight->radius);
7197                 Con_Printf("Corona       : %f\n", r_shadow_selectedlight->corona);
7198                 Con_Printf("Style        : %i\n", r_shadow_selectedlight->style);
7199                 Con_Printf("Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
7200                 Con_Printf("Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);
7201                 Con_Printf("CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);
7202                 Con_Printf("Ambient      : %f\n", r_shadow_selectedlight->ambientscale);
7203                 Con_Printf("Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);
7204                 Con_Printf("Specular     : %f\n", r_shadow_selectedlight->specularscale);
7205                 Con_Printf("NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");
7206                 Con_Printf("RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");
7207                 return;
7208         }
7209         flags = (normalmode ? LIGHTFLAG_NORMALMODE : 0) | (realtimemode ? LIGHTFLAG_REALTIMEMODE : 0);
7210         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
7211 }
7212
7213 static void R_Shadow_EditLights_EditAll_f(void)
7214 {
7215         size_t lightindex;
7216         dlight_t *light, *oldselected;
7217         size_t range;
7218
7219         if (!r_editlights.integer)
7220         {
7221                 Con_Print("Cannot edit lights when not in editing mode. Set r_editlights to 1.\n");
7222                 return;
7223         }
7224
7225         oldselected = r_shadow_selectedlight;
7226         // EditLights doesn't seem to have a "remove" command or something so:
7227         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7228         for (lightindex = 0;lightindex < range;lightindex++)
7229         {
7230                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7231                 if (!light)
7232                         continue;
7233                 R_Shadow_SelectLight(light);
7234                 R_Shadow_EditLights_Edit_f();
7235         }
7236         // return to old selected (to not mess editing once selection is locked)
7237         R_Shadow_SelectLight(oldselected);
7238 }
7239
7240 void R_Shadow_EditLights_DrawSelectedLightProperties(void)
7241 {
7242         int lightnumber, lightcount;
7243         size_t lightindex, range;
7244         dlight_t *light;
7245         char temp[256];
7246         float x, y;
7247
7248         if (!r_editlights.integer)
7249                 return;
7250
7251         // update cvars so QC can query them
7252         if (r_shadow_selectedlight)
7253         {
7254                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
7255                 Cvar_SetQuick(&r_editlights_current_origin, temp);
7256                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
7257                 Cvar_SetQuick(&r_editlights_current_angles, temp);
7258                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
7259                 Cvar_SetQuick(&r_editlights_current_color, temp);
7260                 Cvar_SetValueQuick(&r_editlights_current_radius, r_shadow_selectedlight->radius);
7261                 Cvar_SetValueQuick(&r_editlights_current_corona, r_shadow_selectedlight->corona);
7262                 Cvar_SetValueQuick(&r_editlights_current_coronasize, r_shadow_selectedlight->coronasizescale);
7263                 Cvar_SetValueQuick(&r_editlights_current_style, r_shadow_selectedlight->style);
7264                 Cvar_SetValueQuick(&r_editlights_current_shadows, r_shadow_selectedlight->shadow);
7265                 Cvar_SetQuick(&r_editlights_current_cubemap, r_shadow_selectedlight->cubemapname);
7266                 Cvar_SetValueQuick(&r_editlights_current_ambient, r_shadow_selectedlight->ambientscale);
7267                 Cvar_SetValueQuick(&r_editlights_current_diffuse, r_shadow_selectedlight->diffusescale);
7268                 Cvar_SetValueQuick(&r_editlights_current_specular, r_shadow_selectedlight->specularscale);
7269                 Cvar_SetValueQuick(&r_editlights_current_normalmode, (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? 1 : 0);
7270                 Cvar_SetValueQuick(&r_editlights_current_realtimemode, (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? 1 : 0);
7271         }
7272
7273         // draw properties on screen
7274         if (!r_editlights_drawproperties.integer)
7275                 return;
7276         x = vid_conwidth.value - 320;
7277         y = 5;
7278         DrawQ_Pic(x-5, y-5, NULL, 250, 243, 0, 0, 0, 0.75, 0);
7279         lightnumber = -1;
7280         lightcount = 0;
7281         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7282         for (lightindex = 0;lightindex < range;lightindex++)
7283         {
7284                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7285                 if (!light)
7286                         continue;
7287                 if (light == r_shadow_selectedlight)
7288                         lightnumber = (int)lightindex;
7289                 lightcount++;
7290         }
7291         dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
7292         dpsnprintf(temp, sizeof(temp), "Total lights : %i active (%i total)", lightcount, (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
7293         y += 8;
7294         if (r_shadow_selectedlight == NULL)
7295                 return;
7296         dpsnprintf(temp, sizeof(temp), "Light #%i properties:", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7297         dpsnprintf(temp, sizeof(temp), "Origin       : %.0f %.0f %.0f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7298         dpsnprintf(temp, sizeof(temp), "Angles       : %.0f %.0f %.0f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7299         dpsnprintf(temp, sizeof(temp), "Color        : %.2f %.2f %.2f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7300         dpsnprintf(temp, sizeof(temp), "Radius       : %.0f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7301         dpsnprintf(temp, sizeof(temp), "Corona       : %.0f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7302         dpsnprintf(temp, sizeof(temp), "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7303         dpsnprintf(temp, sizeof(temp), "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7304         dpsnprintf(temp, sizeof(temp), "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7305         dpsnprintf(temp, sizeof(temp), "CoronaSize   : %.2f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7306         dpsnprintf(temp, sizeof(temp), "Ambient      : %.2f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7307         dpsnprintf(temp, sizeof(temp), "Diffuse      : %.2f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7308         dpsnprintf(temp, sizeof(temp), "Specular     : %.2f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7309         dpsnprintf(temp, sizeof(temp), "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7310         dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
7311         y += 8;
7312         dpsnprintf(temp, sizeof(temp), "Render stats\n"); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7313         dpsnprintf(temp, sizeof(temp), "Current color: %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.currentcolor[0], r_shadow_selectedlight->rtlight.currentcolor[1], r_shadow_selectedlight->rtlight.currentcolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7314         dpsnprintf(temp, sizeof(temp), "Shadow size  : %ix%ix6\n", r_shadow_selectedlight->rtlight.shadowmapatlassidesize, r_shadow_selectedlight->rtlight.shadowmapatlassidesize); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7315         dpsnprintf(temp, sizeof(temp), "World surfs  : %i\n", r_shadow_selectedlight->rtlight.cached_numsurfaces); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7316         dpsnprintf(temp, sizeof(temp), "Shadow ents  : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numshadowentities, r_shadow_selectedlight->rtlight.cached_numshadowentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7317         dpsnprintf(temp, sizeof(temp), "Lit ents     : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numlightentities, r_shadow_selectedlight->rtlight.cached_numlightentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7318         dpsnprintf(temp, sizeof(temp), "BG photons   : %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photons); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7319         dpsnprintf(temp, sizeof(temp), "BG radius    : %.0f\n", r_shadow_selectedlight->rtlight.bouncegrid_effectiveradius); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7320         dpsnprintf(temp, sizeof(temp), "BG color     : %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[0], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[1], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7321         dpsnprintf(temp, sizeof(temp), "BG stats     : %i traces %i hits\n", r_shadow_selectedlight->rtlight.bouncegrid_traces, r_shadow_selectedlight->rtlight.bouncegrid_hits); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
7322 }
7323
7324 static void R_Shadow_EditLights_ToggleShadow_f(void)
7325 {
7326         if (!r_editlights.integer)
7327         {
7328                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7329                 return;
7330         }
7331         if (!r_shadow_selectedlight)
7332         {
7333                 Con_Print("No selected light.\n");
7334                 return;
7335         }
7336         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
7337 }
7338
7339 static void R_Shadow_EditLights_ToggleCorona_f(void)
7340 {
7341         if (!r_editlights.integer)
7342         {
7343                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7344                 return;
7345         }
7346         if (!r_shadow_selectedlight)
7347         {
7348                 Con_Print("No selected light.\n");
7349                 return;
7350         }
7351         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
7352 }
7353
7354 static void R_Shadow_EditLights_Remove_f(void)
7355 {
7356         if (!r_editlights.integer)
7357         {
7358                 Con_Print("Cannot remove light when not in editing mode.  Set r_editlights to 1.\n");
7359                 return;
7360         }
7361         if (!r_shadow_selectedlight)
7362         {
7363                 Con_Print("No selected light.\n");
7364                 return;
7365         }
7366         R_Shadow_FreeWorldLight(r_shadow_selectedlight);
7367         r_shadow_selectedlight = NULL;
7368 }
7369
7370 static void R_Shadow_EditLights_Help_f(void)
7371 {
7372         Con_Print(
7373 "Documentation on r_editlights system:\n"
7374 "Settings:\n"
7375 "r_editlights : enable/disable editing mode\n"
7376 "r_editlights_cursordistance : maximum distance of cursor from eye\n"
7377 "r_editlights_cursorpushback : push back cursor this far from surface\n"
7378 "r_editlights_cursorpushoff : push cursor off surface this far\n"
7379 "r_editlights_cursorgrid : snap cursor to grid of this size\n"
7380 "r_editlights_quakelightsizescale : imported quake light entity size scaling\n"
7381 "Commands:\n"
7382 "r_editlights_help : this help\n"
7383 "r_editlights_clear : remove all lights\n"
7384 "r_editlights_reload : reload .rtlights, .lights file, or entities\n"
7385 "r_editlights_lock : lock selection to current light, if already locked - unlock\n"
7386 "r_editlights_save : save to .rtlights file\n"
7387 "r_editlights_spawn : create a light with default settings\n"
7388 "r_editlights_edit command : edit selected light - more documentation below\n"
7389 "r_editlights_remove : remove selected light\n"
7390 "r_editlights_toggleshadow : toggles on/off selected light's shadow property\n"
7391 "r_editlights_importlightentitiesfrommap : reload light entities\n"
7392 "r_editlights_importlightsfile : reload .light file (produced by hlight)\n"
7393 "Edit commands:\n"
7394 "origin x y z : set light location\n"
7395 "originx x: set x component of light location\n"
7396 "originy y: set y component of light location\n"
7397 "originz z: set z component of light location\n"
7398 "move x y z : adjust light location\n"
7399 "movex x: adjust x component of light location\n"
7400 "movey y: adjust y component of light location\n"
7401 "movez z: adjust z component of light location\n"
7402 "angles x y z : set light angles\n"
7403 "anglesx x: set x component of light angles\n"
7404 "anglesy y: set y component of light angles\n"
7405 "anglesz z: set z component of light angles\n"
7406 "color r g b : set color of light (can be brighter than 1 1 1)\n"
7407 "radius radius : set radius (size) of light\n"
7408 "colorscale grey : multiply color of light (1 does nothing)\n"
7409 "colorscale r g b : multiply color of light (1 1 1 does nothing)\n"
7410 "radiusscale scale : multiply radius (size) of light (1 does nothing)\n"
7411 "sizescale scale : multiply radius (size) of light (1 does nothing)\n"
7412 "originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
7413 "style style : set lightstyle of light (flickering patterns, switches, etc)\n"
7414 "cubemap basename : set filter cubemap of light\n"
7415 "shadows 1/0 : turn on/off shadows\n"
7416 "corona n : set corona intensity\n"
7417 "coronasize n : set corona size (0-1)\n"
7418 "ambient n : set ambient intensity (0-1)\n"
7419 "diffuse n : set diffuse intensity (0-1)\n"
7420 "specular n : set specular intensity (0-1)\n"
7421 "normalmode 1/0 : turn on/off rendering of this light in rtworld 0 mode\n"
7422 "realtimemode 1/0 : turn on/off rendering of this light in rtworld 1 mode\n"
7423 "<nothing> : print light properties to console\n"
7424         );
7425 }
7426
7427 static void R_Shadow_EditLights_CopyInfo_f(void)
7428 {
7429         if (!r_editlights.integer)
7430         {
7431                 Con_Print("Cannot copy light info when not in editing mode.  Set r_editlights to 1.\n");
7432                 return;
7433         }
7434         if (!r_shadow_selectedlight)
7435         {
7436                 Con_Print("No selected light.\n");
7437                 return;
7438         }
7439         VectorCopy(r_shadow_selectedlight->angles, r_shadow_bufferlight.angles);
7440         VectorCopy(r_shadow_selectedlight->color, r_shadow_bufferlight.color);
7441         r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
7442         r_shadow_bufferlight.style = r_shadow_selectedlight->style;
7443         if (r_shadow_selectedlight->cubemapname)
7444                 strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
7445         else
7446                 r_shadow_bufferlight.cubemapname[0] = 0;
7447         r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;
7448         r_shadow_bufferlight.corona = r_shadow_selectedlight->corona;
7449         r_shadow_bufferlight.coronasizescale = r_shadow_selectedlight->coronasizescale;
7450         r_shadow_bufferlight.ambientscale = r_shadow_selectedlight->ambientscale;
7451         r_shadow_bufferlight.diffusescale = r_shadow_selectedlight->diffusescale;
7452         r_shadow_bufferlight.specularscale = r_shadow_selectedlight->specularscale;
7453         r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
7454 }
7455
7456 static void R_Shadow_EditLights_PasteInfo_f(void)
7457 {
7458         if (!r_editlights.integer)
7459         {
7460                 Con_Print("Cannot paste light info when not in editing mode.  Set r_editlights to 1.\n");
7461                 return;
7462         }
7463         if (!r_shadow_selectedlight)
7464         {
7465                 Con_Print("No selected light.\n");
7466                 return;
7467         }
7468         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname, r_shadow_bufferlight.coronasizescale, r_shadow_bufferlight.ambientscale, r_shadow_bufferlight.diffusescale, r_shadow_bufferlight.specularscale, r_shadow_bufferlight.flags);
7469 }
7470
7471 static void R_Shadow_EditLights_Lock_f(void)
7472 {
7473         if (!r_editlights.integer)
7474         {
7475                 Con_Print("Cannot lock on light when not in editing mode.  Set r_editlights to 1.\n");
7476                 return;
7477         }
7478         if (r_editlights_lockcursor)
7479         {
7480                 r_editlights_lockcursor = false;
7481                 return;
7482         }
7483         if (!r_shadow_selectedlight)
7484         {
7485                 Con_Print("No selected light to lock on.\n");
7486                 return;
7487         }
7488         r_editlights_lockcursor = true;
7489 }
7490
7491 static void R_Shadow_EditLights_Init(void)
7492 {
7493         Cvar_RegisterVariable(&r_editlights);
7494         Cvar_RegisterVariable(&r_editlights_cursordistance);
7495         Cvar_RegisterVariable(&r_editlights_cursorpushback);
7496         Cvar_RegisterVariable(&r_editlights_cursorpushoff);
7497         Cvar_RegisterVariable(&r_editlights_cursorgrid);
7498         Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
7499         Cvar_RegisterVariable(&r_editlights_drawproperties);
7500         Cvar_RegisterVariable(&r_editlights_current_origin);
7501         Cvar_RegisterVariable(&r_editlights_current_angles);
7502         Cvar_RegisterVariable(&r_editlights_current_color);
7503         Cvar_RegisterVariable(&r_editlights_current_radius);
7504         Cvar_RegisterVariable(&r_editlights_current_corona);
7505         Cvar_RegisterVariable(&r_editlights_current_coronasize);
7506         Cvar_RegisterVariable(&r_editlights_current_style);
7507         Cvar_RegisterVariable(&r_editlights_current_shadows);
7508         Cvar_RegisterVariable(&r_editlights_current_cubemap);
7509         Cvar_RegisterVariable(&r_editlights_current_ambient);
7510         Cvar_RegisterVariable(&r_editlights_current_diffuse);
7511         Cvar_RegisterVariable(&r_editlights_current_specular);
7512         Cvar_RegisterVariable(&r_editlights_current_normalmode);
7513         Cvar_RegisterVariable(&r_editlights_current_realtimemode);
7514         Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
7515         Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
7516         Cmd_AddCommand("r_editlights_reload", R_Shadow_EditLights_Reload_f, "reloads rtlights file (or imports from .lights file or .ent file or the map itself)");
7517         Cmd_AddCommand("r_editlights_save", R_Shadow_EditLights_Save_f, "save .rtlights file for current level");
7518         Cmd_AddCommand("r_editlights_spawn", R_Shadow_EditLights_Spawn_f, "creates a light with default properties (let there be light!)");
7519         Cmd_AddCommand("r_editlights_edit", R_Shadow_EditLights_Edit_f, "changes a property on the selected light");
7520         Cmd_AddCommand("r_editlights_editall", R_Shadow_EditLights_EditAll_f, "changes a property on ALL lights at once (tip: use radiusscale and colorscale to alter these properties)");
7521         Cmd_AddCommand("r_editlights_remove", R_Shadow_EditLights_Remove_f, "remove selected light");
7522         Cmd_AddCommand("r_editlights_toggleshadow", R_Shadow_EditLights_ToggleShadow_f, "toggle on/off the shadow option on the selected light");
7523         Cmd_AddCommand("r_editlights_togglecorona", R_Shadow_EditLights_ToggleCorona_f, "toggle on/off the corona option on the selected light");
7524         Cmd_AddCommand("r_editlights_importlightentitiesfrommap", R_Shadow_EditLights_ImportLightEntitiesFromMap_f, "load lights from .ent file or map entities (ignoring .rtlights or .lights file)");
7525         Cmd_AddCommand("r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)");
7526         Cmd_AddCommand("r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
7527         Cmd_AddCommand("r_editlights_pasteinfo", R_Shadow_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)");
7528         Cmd_AddCommand("r_editlights_lock", R_Shadow_EditLights_Lock_f, "lock selection to current light, if already locked - unlock");
7529 }
7530
7531
7532
7533 /*
7534 =============================================================================
7535
7536 LIGHT SAMPLING
7537
7538 =============================================================================
7539 */
7540
7541 void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity)
7542 {
7543         int i, numlights, flag, q;
7544         rtlight_t *light;
7545         dlight_t *dlight;
7546         float relativepoint[3];
7547         float color[3];
7548         float dist;
7549         float dist2;
7550         float intensity;
7551         float sa[3], sx[3], sy[3], sz[3], sd[3];
7552         float lightradius2;
7553
7554         // use first order spherical harmonics to combine directional lights
7555         for (q = 0; q < 3; q++)
7556                 sa[q] = sx[q] = sy[q] = sz[q] = sd[q] = 0;
7557
7558         if (flags & LP_LIGHTMAP)
7559         {
7560                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7561                 {
7562                         float tempambient[3];
7563                         for (q = 0; q < 3; q++)
7564                                 tempambient[q] = color[q] = relativepoint[q] = 0;
7565                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
7566                         // calculate a weighted average light direction as well
7567                         intensity = VectorLength(color);
7568                         for (q = 0; q < 3; q++)
7569                         {
7570                                 sa[q] += (0.5f * color[q] + tempambient[q]) * lightmapintensity;
7571                                 sx[q] += (relativepoint[0] * color[q]) * lightmapintensity;
7572                                 sy[q] += (relativepoint[1] * color[q]) * lightmapintensity;
7573                                 sz[q] += (relativepoint[2] * color[q]) * lightmapintensity;
7574                                 sd[q] += (intensity * relativepoint[q]) * lightmapintensity;
7575                         }
7576                 }
7577                 else
7578                 {
7579                         // unlit map - fullbright but scaled by lightmapintensity
7580                         for (q = 0; q < 3; q++)
7581                                 sa[q] += lightmapintensity;
7582                 }
7583         }
7584
7585         if (flags & LP_RTWORLD)
7586         {
7587                 flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
7588                 numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
7589                 for (i = 0; i < numlights; i++)
7590                 {
7591                         dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
7592                         if (!dlight)
7593                                 continue;
7594                         light = &dlight->rtlight;
7595                         if (!(light->flags & flag))
7596                                 continue;
7597                         // sample
7598                         lightradius2 = light->radius * light->radius;
7599                         VectorSubtract(light->shadoworigin, p, relativepoint);
7600                         dist2 = VectorLength2(relativepoint);
7601                         if (dist2 >= lightradius2)
7602                                 continue;
7603                         dist = sqrt(dist2) / light->radius;
7604                         intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
7605                         if (intensity <= 0.0f)
7606                                 continue;
7607                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7608                                 continue;
7609                         for (q = 0; q < 3; q++)
7610                                 color[q] = light->currentcolor[q] * intensity;
7611                         intensity = VectorLength(color);
7612                         VectorNormalize(relativepoint);
7613                         for (q = 0; q < 3; q++)
7614                         {
7615                                 sa[q] += 0.5f * color[q];
7616                                 sx[q] += relativepoint[0] * color[q];
7617                                 sy[q] += relativepoint[1] * color[q];
7618                                 sz[q] += relativepoint[2] * color[q];
7619                                 sd[q] += intensity * relativepoint[q];
7620                         }
7621                 }
7622                 // FIXME: sample bouncegrid too!
7623         }
7624
7625         if (flags & LP_DYNLIGHT)
7626         {
7627                 // sample dlights
7628                 for (i = 0;i < r_refdef.scene.numlights;i++)
7629                 {
7630                         light = r_refdef.scene.lights[i];
7631                         // sample
7632                         lightradius2 = light->radius * light->radius;
7633                         VectorSubtract(light->shadoworigin, p, relativepoint);
7634                         dist2 = VectorLength2(relativepoint);
7635                         if (dist2 >= lightradius2)
7636                                 continue;
7637                         dist = sqrt(dist2) / light->radius;
7638                         intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
7639                         if (intensity <= 0.0f)
7640                                 continue;
7641                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7642                                 continue;
7643                         for (q = 0; q < 3; q++)
7644                                 color[q] = light->currentcolor[q] * intensity;
7645                         intensity = VectorLength(color);
7646                         VectorNormalize(relativepoint);
7647                         for (q = 0; q < 3; q++)
7648                         {
7649                                 sa[q] += 0.5f * color[q];
7650                                 sx[q] += relativepoint[0] * color[q];
7651                                 sy[q] += relativepoint[1] * color[q];
7652                                 sz[q] += relativepoint[2] * color[q];
7653                                 sd[q] += intensity * relativepoint[q];
7654                         }
7655                 }
7656         }
7657
7658         // calculate the weighted-average light direction (bentnormal)
7659         for (q = 0; q < 3; q++)
7660                 lightdir[q] = sd[q];
7661         VectorNormalize(lightdir);
7662         for (q = 0; q < 3; q++)
7663         {
7664                 // extract the diffuse color along the chosen direction and scale it
7665                 diffuse[q] = (lightdir[0] * sx[q] + lightdir[1] * sy[q] + lightdir[2] * sz[q]);
7666                 // subtract some of diffuse from ambient
7667                 ambient[q] = sa[q] + -0.333f * diffuse[q] + ambientintensity;
7668         }
7669 }