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