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