]> git.xonotic.org Git - xonotic/darkplaces.git/blob - r_shadow.c
Fix another bug in R_Shadow_PrepareLights_AddSceneLight - it was not increasing r_sha...
[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_scenemaxlights <= r_shadow_scenenumlights)
5068         {
5069                 if (r_shadow_scenenumlights >= MAX_SCENELIGHTS)
5070                         return false;
5071                 r_shadow_scenemaxlights *= 2;
5072                 r_shadow_scenemaxlights = bound(1024, r_shadow_scenemaxlights, MAX_SCENELIGHTS);
5073                 r_shadow_scenelightlist = (rtlight_t **)Mem_Realloc(r_main_mempool, r_shadow_scenelightlist, r_shadow_scenemaxlights * sizeof(rtlight_t *));
5074         }
5075         r_shadow_scenelightlist[r_shadow_scenenumlights++] = rtlight;
5076         return true;
5077 }
5078
5079 void R_Shadow_DrawLightSprites(void);
5080 void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5081 {
5082         int flag;
5083         int lnum;
5084         size_t lightindex;
5085         dlight_t *light;
5086         size_t range;
5087         float f;
5088
5089         int shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
5090         int shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
5091         int shadowmapmaxsize = bound(shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, shadowmaptexturesize / 8);
5092
5093         if (r_shadow_shadowmaptexturesize != shadowmaptexturesize ||
5094                 (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
5095                 r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) ||
5096                 r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
5097                 r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
5098                 r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
5099                 r_shadow_shadowmapborder != shadowmapborder ||
5100                 r_shadow_shadowmapmaxsize != shadowmapmaxsize ||
5101                 r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
5102                 R_Shadow_FreeShadowMaps();
5103
5104         r_shadow_fb_fbo = fbo;
5105         r_shadow_fb_depthtexture = depthtexture;
5106         r_shadow_fb_colortexture = colortexture;
5107
5108         r_shadow_usingshadowmaportho = false;
5109
5110         switch (vid.renderpath)
5111         {
5112         case RENDERPATH_GL20:
5113         case RENDERPATH_D3D9:
5114         case RENDERPATH_D3D10:
5115         case RENDERPATH_D3D11:
5116         case RENDERPATH_SOFT:
5117 #ifndef USE_GLES2
5118                 if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
5119                 {
5120                         r_shadow_usingdeferredprepass = false;
5121                         if (r_shadow_prepass_width)
5122                                 R_Shadow_FreeDeferred();
5123                         r_shadow_prepass_width = r_shadow_prepass_height = 0;
5124                         break;
5125                 }
5126
5127                 if (r_shadow_prepass_width != vid.width || r_shadow_prepass_height != vid.height)
5128                 {
5129                         R_Shadow_FreeDeferred();
5130
5131                         r_shadow_usingdeferredprepass = true;
5132                         r_shadow_prepass_width = vid.width;
5133                         r_shadow_prepass_height = vid.height;
5134                         r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
5135                         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);
5136                         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);
5137                         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);
5138
5139                         // set up the geometry pass fbo (depth + normalmap)
5140                         r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5141                         R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5142                         // render depth into a renderbuffer and other important properties into the normalmap texture
5143
5144                         // set up the lighting pass fbo (diffuse + specular)
5145                         r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5146                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5147                         // render diffuse into one texture and specular into another,
5148                         // with depth and normalmap bound as textures,
5149                         // with depth bound as attachment as well
5150
5151                         // set up the lighting pass fbo (diffuse)
5152                         r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5153                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5154                         // render diffuse into one texture,
5155                         // with depth and normalmap bound as textures,
5156                         // with depth bound as attachment as well
5157                 }
5158 #endif
5159                 break;
5160         case RENDERPATH_GL11:
5161         case RENDERPATH_GL13:
5162         case RENDERPATH_GLES1:
5163         case RENDERPATH_GLES2:
5164                 r_shadow_usingdeferredprepass = false;
5165                 break;
5166         }
5167
5168         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);
5169
5170         r_shadow_scenenumlights = 0;
5171         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
5172         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5173         for (lightindex = 0; lightindex < range; lightindex++)
5174         {
5175                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5176                 if (light && (light->flags & flag))
5177                 {
5178                         R_Shadow_PrepareLight(&light->rtlight);
5179                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5180                 }
5181         }
5182         if (r_refdef.scene.rtdlight)
5183         {
5184                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5185                 {
5186                         R_Shadow_PrepareLight(r_refdef.scene.lights[lnum]);
5187                         R_Shadow_PrepareLights_AddSceneLight(r_refdef.scene.lights[lnum]);
5188                 }
5189         }
5190         else if (gl_flashblend.integer)
5191         {
5192                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5193                 {
5194                         rtlight_t *rtlight = r_refdef.scene.lights[lnum];
5195                         f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
5196                         VectorScale(rtlight->color, f, rtlight->currentcolor);
5197                 }
5198         }
5199
5200         // when debugging a single light, we still want to run the prepare, so we only replace the light list afterward...
5201         if (r_shadow_debuglight.integer >= 0)
5202         {
5203                 r_shadow_scenenumlights = 0;
5204                 lightindex = r_shadow_debuglight.integer;
5205                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5206                 if (light)
5207                 {
5208                         R_Shadow_PrepareLight(&light->rtlight);
5209                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5210                 }
5211         }
5212
5213         // if we're doing shadowmaps we need to prepare the atlas layout now
5214         if (R_Shadow_ShadowMappingEnabled())
5215         {
5216                 int lod;
5217
5218                 // allocate shadowmaps in the atlas now
5219                 // 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...
5220                 for (lod = 0; lod < 16; lod++)
5221                 {
5222                         int packing_success = 0;
5223                         int packing_failure = 0;
5224                         Mod_AllocLightmap_Reset(&r_shadow_shadowmapatlas_state);
5225                         // we actually have to reserve space for the R_DrawModelShadowMaps if that feature is active, it uses 0,0 so this is easy.
5226                         if (r_shadow_shadowmapatlas_modelshadows_size)
5227                                 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);
5228                         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5229                         {
5230                                 rtlight_t *rtlight = r_shadow_scenelightlist[lnum];
5231                                 int size = rtlight->shadowmapsidesize >> lod;
5232                                 int width, height;
5233                                 if (!rtlight->castshadows)
5234                                         continue;
5235                                 size = bound(r_shadow_shadowmapborder, size, r_shadow_shadowmaptexturesize);
5236                                 width = size * 2;
5237                                 height = size * 3;
5238                                 // when there are noselfshadow entities in the light bounds, we have to render two separate sets of shadowmaps :(
5239                                 if (rtlight->cached_numshadowentities_noselfshadow)
5240                                         width *= 2;
5241                                 if (Mod_AllocLightmap_Block(&r_shadow_shadowmapatlas_state, width, height, &rtlight->shadowmapatlasposition[0], &rtlight->shadowmapatlasposition[1]))
5242                                 {
5243                                         rtlight->shadowmapatlassidesize = size;
5244                                         packing_success++;
5245                                 }
5246                                 else
5247                                 {
5248                                         // note down that we failed to pack this one, it will have to disable shadows
5249                                         rtlight->shadowmapatlassidesize = 0;
5250                                         packing_failure++;
5251                                 }
5252                         }
5253                         // generally everything fits and we stop here on the first iteration
5254                         if (packing_failure == 0)
5255                                 break;
5256                 }
5257         }
5258
5259         if (r_editlights.integer)
5260                 R_Shadow_DrawLightSprites();
5261 }
5262
5263 void R_Shadow_DrawShadowMaps(void)
5264 {
5265         R_Shadow_RenderMode_Begin();
5266         R_Shadow_RenderMode_ActiveLight(NULL);
5267
5268         // now that we have a layout of shadowmaps in the atlas, we can render the shadowmaps
5269         R_Shadow_ClearShadowMapTexture();
5270
5271         // render model shadowmaps (r_shadows 2) if desired which will be sampled in the forward pass
5272         if (r_shadow_shadowmapatlas_modelshadows_size)
5273         {
5274                 R_Shadow_DrawModelShadowMaps();
5275                 // don't let sound skip if going slow
5276                 if (r_refdef.scene.extraupdate)
5277                         S_ExtraUpdate();
5278         }
5279
5280         if (R_Shadow_ShadowMappingEnabled())
5281         {
5282                 int lnum;
5283                 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5284                         R_Shadow_DrawLightShadowMaps(r_shadow_scenelightlist[lnum]);
5285         }
5286
5287         R_Shadow_RenderMode_End();
5288 }
5289
5290 void R_Shadow_DrawLights(void)
5291 {
5292         int lnum;
5293
5294         R_Shadow_RenderMode_Begin();
5295
5296         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5297                 R_Shadow_DrawLight(r_shadow_scenelightlist[lnum]);
5298
5299         R_Shadow_RenderMode_End();
5300 }
5301
5302 #define MAX_MODELSHADOWS 1024
5303 static int r_shadow_nummodelshadows;
5304 static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS];
5305
5306 void R_Shadow_PrepareModelShadows(void)
5307 {
5308         int i;
5309         float scale, size, radius, dot1, dot2;
5310         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5311         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
5312         entity_render_t *ent;
5313
5314         r_shadow_nummodelshadows = 0;
5315         r_shadow_shadowmapatlas_modelshadows_size = 0;
5316
5317         if (!r_refdef.scene.numentities || r_refdef.lightmapintensity <= 0.0f || r_shadows.integer <= 0)
5318                 return;
5319
5320         switch (r_shadow_shadowmode)
5321         {
5322         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
5323                 if (r_shadows.integer >= 2)
5324                         break;
5325                 // fall through
5326         case R_SHADOW_SHADOWMODE_STENCIL:
5327                 if (!vid.stencil)
5328                         return;
5329                 for (i = 0; i < r_refdef.scene.numentities; i++)
5330                 {
5331                         ent = r_refdef.scene.entities[i];
5332                         if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5333                         {
5334                                 if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5335                                         break;
5336                                 r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5337                                 R_AnimCache_GetEntity(ent, false, false);
5338                         }
5339                 }
5340                 return;
5341         default:
5342                 return;
5343         }
5344
5345         size = 2 * r_shadow_shadowmapmaxsize;
5346         scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
5347         radius = 0.5f * size / scale;
5348
5349         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5350         VectorCopy(prvmshadowdir, shadowdir);
5351         VectorNormalize(shadowdir);
5352         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5353         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5354         if (fabs(dot1) <= fabs(dot2))
5355                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5356         else
5357                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5358         VectorNormalize(shadowforward);
5359         CrossProduct(shadowdir, shadowforward, shadowright);
5360         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5361         VectorCopy(prvmshadowfocus, shadowfocus);
5362         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5363         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5364         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5365         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5366         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5367                 dot1 = 1;
5368         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5369
5370         shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5371         shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5372         shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5373         shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5374         shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5375         shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5376
5377         for (i = 0; i < r_refdef.scene.numentities; i++)
5378         {
5379                 ent = r_refdef.scene.entities[i];
5380                 if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
5381                         continue;
5382                 // cast shadows from anything of the map (submodels are optional)
5383                 if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5384                 {
5385                         if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5386                                 break;
5387                         r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5388                         R_AnimCache_GetEntity(ent, false, false);
5389                 }
5390         }
5391
5392         if (r_shadow_nummodelshadows)
5393         {
5394                 r_shadow_shadowmapatlas_modelshadows_x = 0;
5395                 r_shadow_shadowmapatlas_modelshadows_y = 0;
5396                 r_shadow_shadowmapatlas_modelshadows_size = size;
5397         }
5398 }
5399
5400 static void R_Shadow_DrawModelShadowMaps(void)
5401 {
5402         int i;
5403         float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
5404         entity_render_t *ent;
5405         vec3_t relativelightorigin;
5406         vec3_t relativelightdirection, relativeforward, relativeright;
5407         vec3_t relativeshadowmins, relativeshadowmaxs;
5408         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
5409         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5410         float m[12];
5411         matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
5412         r_viewport_t viewport;
5413
5414         size = r_shadow_shadowmapatlas_modelshadows_size;
5415         scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size;
5416         radius = 0.5f / scale;
5417         nearclip = -r_shadows_throwdistance.value;
5418         farclip = r_shadows_throwdistance.value;
5419         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);
5420
5421         // set the parameters that will be used on the regular model renders using these shadows we're about to produce
5422         r_shadow_modelshadowmap_parameters[0] = size;
5423         r_shadow_modelshadowmap_parameters[1] = size;
5424         r_shadow_modelshadowmap_parameters[2] = 1.0;
5425         r_shadow_modelshadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
5426         r_shadow_modelshadowmap_texturescale[0] = 1.0f / r_shadow_shadowmaptexturesize;
5427         r_shadow_modelshadowmap_texturescale[1] = 1.0f / r_shadow_shadowmaptexturesize;
5428         r_shadow_modelshadowmap_texturescale[2] = r_shadow_shadowmapatlas_modelshadows_x;
5429         r_shadow_modelshadowmap_texturescale[3] = r_shadow_shadowmapatlas_modelshadows_y;
5430         r_shadow_usingshadowmaportho = true;
5431
5432         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5433         VectorCopy(prvmshadowdir, shadowdir);
5434         VectorNormalize(shadowdir);
5435         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5436         VectorCopy(prvmshadowfocus, shadowfocus);
5437         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5438         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5439         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5440         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5441         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5442         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5443         if (fabs(dot1) <= fabs(dot2)) 
5444                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5445         else
5446                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5447         VectorNormalize(shadowforward);
5448         VectorM(scale, shadowforward, &m[0]);
5449         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5450                 dot1 = 1;
5451         m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
5452         CrossProduct(shadowdir, shadowforward, shadowright);
5453         VectorM(scale, shadowright, &m[4]);
5454         m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
5455         VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
5456         m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
5457         Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
5458         Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
5459         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);
5460         R_SetViewport(&viewport);
5461
5462         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5463
5464         // render into a slightly restricted region so that the borders of the
5465         // shadowmap area fade away, rather than streaking across everything
5466         // outside the usable area
5467         GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
5468
5469         for (i = 0;i < r_shadow_nummodelshadows;i++)
5470         {
5471                 ent = r_shadow_modelshadows[i];
5472                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5473                 Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
5474                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5475                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
5476                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
5477                 relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5478                 relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5479                 relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5480                 relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5481                 relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5482                 relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5483                 RSurf_ActiveModelEntity(ent, false, false, false);
5484                 ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
5485                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5486         }
5487
5488 #if 0
5489         if (r_test.integer)
5490         {
5491                 unsigned char *rawpixels = Z_Malloc(viewport.width*viewport.height*4);
5492                 CHECKGLERROR
5493                 qglReadPixels(viewport.x, viewport.y, viewport.width, viewport.height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, rawpixels);
5494                 CHECKGLERROR
5495                 Image_WriteTGABGRA("r_shadows_2.tga", viewport.width, viewport.height, rawpixels);
5496                 Cvar_SetValueQuick(&r_test, 0);
5497                 Z_Free(rawpixels);
5498         }
5499 #endif
5500
5501         Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5502         Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5503         Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); 
5504         Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
5505         Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
5506         Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
5507
5508         switch (vid.renderpath)
5509         {
5510         case RENDERPATH_GL11:
5511         case RENDERPATH_GL13:
5512         case RENDERPATH_GL20:
5513         case RENDERPATH_SOFT:
5514         case RENDERPATH_GLES1:
5515         case RENDERPATH_GLES2:
5516                 break;
5517         case RENDERPATH_D3D9:
5518         case RENDERPATH_D3D10:
5519         case RENDERPATH_D3D11:
5520 #ifdef MATRIX4x4_OPENGLORIENTATION
5521                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5522                 r_shadow_shadowmapmatrix.m[0][1]        *= -1.0f;
5523                 r_shadow_shadowmapmatrix.m[0][2]        *= -1.0f;
5524                 r_shadow_shadowmapmatrix.m[0][3]        *= -1.0f;
5525 #else
5526                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5527                 r_shadow_shadowmapmatrix.m[1][0]        *= -1.0f;
5528                 r_shadow_shadowmapmatrix.m[2][0]        *= -1.0f;
5529                 r_shadow_shadowmapmatrix.m[3][0]        *= -1.0f;
5530 #endif
5531                 break;
5532         }
5533 }
5534
5535 void R_Shadow_DrawModelShadows(void)
5536 {
5537         int i;
5538         float relativethrowdistance;
5539         entity_render_t *ent;
5540         vec3_t relativelightorigin;
5541         vec3_t relativelightdirection;
5542         vec3_t relativeshadowmins, relativeshadowmaxs;
5543         vec3_t tmp, shadowdir;
5544         prvm_vec3_t prvmshadowdir;
5545
5546         if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
5547                 return;
5548
5549         R_ResetViewRendering3D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5550         //GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5551         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5552         R_Shadow_RenderMode_Begin();
5553         R_Shadow_RenderMode_ActiveLight(NULL);
5554         r_shadow_lightscissor[0] = r_refdef.view.x;
5555         r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
5556         r_shadow_lightscissor[2] = r_refdef.view.width;
5557         r_shadow_lightscissor[3] = r_refdef.view.height;
5558         R_Shadow_RenderMode_StencilShadowVolumes(false);
5559
5560         // get shadow dir
5561         if (r_shadows.integer == 2)
5562         {
5563                 Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5564                 VectorCopy(prvmshadowdir, shadowdir);
5565                 VectorNormalize(shadowdir);
5566         }
5567
5568         R_Shadow_ClearStencil();
5569
5570         for (i = 0;i < r_shadow_nummodelshadows;i++)
5571         {
5572                 ent = r_shadow_modelshadows[i];
5573
5574                 // cast shadows from anything of the map (submodels are optional)
5575                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5576                 VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
5577                 VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
5578                 if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
5579                         Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5580                 else
5581                 {
5582                         if(ent->entitynumber != 0)
5583                         {
5584                                 if(ent->entitynumber >= MAX_EDICTS) // csqc entity
5585                                 {
5586                                         // FIXME handle this
5587                                         VectorNegate(ent->modellight_lightdir, relativelightdirection);
5588                                 }
5589                                 else
5590                                 {
5591                                         // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
5592                                         int entnum, entnum2, recursion;
5593                                         entnum = entnum2 = ent->entitynumber;
5594                                         for(recursion = 32; recursion > 0; --recursion)
5595                                         {
5596                                                 entnum2 = cl.entities[entnum].state_current.tagentity;
5597                                                 if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
5598                                                         entnum = entnum2;
5599                                                 else
5600                                                         break;
5601                                         }
5602                                         if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
5603                                         {
5604                                                 VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
5605                                                 // transform into modelspace of OUR entity
5606                                                 Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
5607                                                 Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
5608                                         }
5609                                         else
5610                                                 VectorNegate(ent->modellight_lightdir, relativelightdirection);
5611                                 }
5612                         }
5613                         else
5614                                 VectorNegate(ent->modellight_lightdir, relativelightdirection);
5615                 }
5616
5617                 VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
5618                 RSurf_ActiveModelEntity(ent, false, false, false);
5619                 ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
5620                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5621         }
5622
5623         // not really the right mode, but this will disable any silly stencil features
5624         R_Shadow_RenderMode_End();
5625
5626         // set up ortho view for rendering this pass
5627         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5628         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5629         //GL_ScissorTest(true);
5630         //R_EntityMatrix(&identitymatrix);
5631         //R_Mesh_ResetTextureState();
5632         R_ResetViewRendering2D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5633
5634         // set up a darkening blend on shadowed areas
5635         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5636         //GL_DepthRange(0, 1);
5637         //GL_DepthTest(false);
5638         //GL_DepthMask(false);
5639         //GL_PolygonOffset(0, 0);CHECKGLERROR
5640         GL_Color(0, 0, 0, r_shadows_darken.value);
5641         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5642         //GL_DepthFunc(GL_ALWAYS);
5643         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_NOTEQUAL, 128, 255);
5644
5645         // apply the blend to the shadowed areas
5646         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
5647         R_SetupShader_Generic_NoTexture(false, true);
5648         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5649
5650         // restore the viewport
5651         R_SetViewport(&r_refdef.view.viewport);
5652
5653         // restore other state to normal
5654         //R_Shadow_RenderMode_End();
5655 }
5656
5657 static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
5658 {
5659         float zdist;
5660         vec3_t centerorigin;
5661 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5662         float vertex3f[12];
5663 #endif
5664         // if it's too close, skip it
5665         if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
5666                 return;
5667         zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
5668         if (zdist < 32)
5669                 return;
5670         if (usequery && r_numqueries + 2 <= r_maxqueries)
5671         {
5672                 rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
5673                 rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
5674                 // 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
5675                 VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
5676
5677                 switch(vid.renderpath)
5678                 {
5679                 case RENDERPATH_GL11:
5680                 case RENDERPATH_GL13:
5681                 case RENDERPATH_GL20:
5682                 case RENDERPATH_GLES1:
5683                 case RENDERPATH_GLES2:
5684 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5685                         CHECKGLERROR
5686                         // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
5687                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
5688                         GL_DepthFunc(GL_ALWAYS);
5689                         R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5690                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5691                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5692                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5693                         GL_DepthFunc(GL_LEQUAL);
5694                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
5695                         R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5696                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5697                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5698                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5699                         CHECKGLERROR
5700 #endif
5701                         break;
5702                 case RENDERPATH_D3D9:
5703                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5704                         break;
5705                 case RENDERPATH_D3D10:
5706                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5707                         break;
5708                 case RENDERPATH_D3D11:
5709                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5710                         break;
5711                 case RENDERPATH_SOFT:
5712                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5713                         break;
5714                 }
5715         }
5716         rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
5717 }
5718
5719 static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5720
5721 static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
5722 {
5723         vec3_t color;
5724         unsigned int occlude = 0;
5725         GLint allpixels = 0, visiblepixels = 0;
5726
5727         // now we have to check the query result
5728         if (rtlight->corona_queryindex_visiblepixels)
5729         {
5730                 switch(vid.renderpath)
5731                 {
5732                 case RENDERPATH_GL11:
5733                 case RENDERPATH_GL13:
5734                 case RENDERPATH_GL20:
5735                 case RENDERPATH_GLES1:
5736                 case RENDERPATH_GLES2:
5737 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5738                         CHECKGLERROR
5739                         // See if we can use the GPU-side method to prevent implicit sync
5740                         if (vid.support.arb_query_buffer_object) {
5741 #define BUFFER_OFFSET(i)    ((GLint *)((unsigned char*)NULL + (i)))
5742                                 if (!r_shadow_occlusion_buf) {
5743                                         qglGenBuffersARB(1, &r_shadow_occlusion_buf);
5744                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5745                                         qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
5746                                 } else {
5747                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5748                                 }
5749                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
5750                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
5751                                 qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
5752                                 occlude = MATERIALFLAG_OCCLUDE;
5753                         } else {
5754                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
5755                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels); 
5756                                 if (visiblepixels < 1 || allpixels < 1)
5757                                         return;
5758                                 rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
5759                         }
5760                         cscale *= rtlight->corona_visibility;
5761                         CHECKGLERROR
5762                         break;
5763 #else
5764                         return;
5765 #endif
5766                 case RENDERPATH_D3D9:
5767                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5768                         return;
5769                 case RENDERPATH_D3D10:
5770                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5771                         return;
5772                 case RENDERPATH_D3D11:
5773                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5774                         return;
5775                 case RENDERPATH_SOFT:
5776                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5777                         return;
5778                 default:
5779                         return;
5780                 }
5781         }
5782         else
5783         {
5784                 // FIXME: these traces should scan all render entities instead of cl.world
5785                 if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
5786                         return;
5787         }
5788         VectorScale(rtlight->currentcolor, cscale, color);
5789         if (VectorLength(color) > (1.0f / 256.0f))
5790         {
5791                 float vertex3f[12];
5792                 qboolean negated = (color[0] + color[1] + color[2] < 0) && vid.support.ext_blend_subtract;
5793                 if(negated)
5794                 {
5795                         VectorNegate(color, color);
5796                         GL_BlendEquationSubtract(true);
5797                 }
5798                 R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5799                 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);
5800                 R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false);
5801                 if(negated)
5802                         GL_BlendEquationSubtract(false);
5803         }
5804 }
5805
5806 void R_Shadow_DrawCoronas(void)
5807 {
5808         int i, flag;
5809         qboolean usequery = false;
5810         size_t lightindex;
5811         dlight_t *light;
5812         rtlight_t *rtlight;
5813         size_t range;
5814         if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
5815                 return;
5816         if (r_fb.water.renderingscene)
5817                 return;
5818         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
5819         R_EntityMatrix(&identitymatrix);
5820
5821         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5822
5823         // check occlusion of coronas
5824         // use GL_ARB_occlusion_query if available
5825         // otherwise use raytraces
5826         r_numqueries = 0;
5827         switch (vid.renderpath)
5828         {
5829         case RENDERPATH_GL11:
5830         case RENDERPATH_GL13:
5831         case RENDERPATH_GL20:
5832         case RENDERPATH_GLES1:
5833         case RENDERPATH_GLES2:
5834                 usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
5835 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5836                 if (usequery)
5837                 {
5838                         GL_ColorMask(0,0,0,0);
5839                         if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
5840                         if (r_maxqueries < MAX_OCCLUSION_QUERIES)
5841                         {
5842                                 i = r_maxqueries;
5843                                 r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
5844                                 r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
5845                                 CHECKGLERROR
5846                                 qglGenQueriesARB(r_maxqueries - i, r_queries + i);
5847                                 CHECKGLERROR
5848                         }
5849                         RSurf_ActiveWorldEntity();
5850                         GL_BlendFunc(GL_ONE, GL_ZERO);
5851                         GL_CullFace(GL_NONE);
5852                         GL_DepthMask(false);
5853                         GL_DepthRange(0, 1);
5854                         GL_PolygonOffset(0, 0);
5855                         GL_DepthTest(true);
5856                         R_Mesh_ResetTextureState();
5857                         R_SetupShader_Generic_NoTexture(false, false);
5858                 }
5859 #endif
5860                 break;
5861         case RENDERPATH_D3D9:
5862                 usequery = false;
5863                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5864                 break;
5865         case RENDERPATH_D3D10:
5866                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5867                 break;
5868         case RENDERPATH_D3D11:
5869                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5870                 break;
5871         case RENDERPATH_SOFT:
5872                 usequery = false;
5873                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5874                 break;
5875         }
5876         for (lightindex = 0;lightindex < range;lightindex++)
5877         {
5878                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5879                 if (!light)
5880                         continue;
5881                 rtlight = &light->rtlight;
5882                 rtlight->corona_visibility = 0;
5883                 rtlight->corona_queryindex_visiblepixels = 0;
5884                 rtlight->corona_queryindex_allpixels = 0;
5885                 if (!(rtlight->flags & flag))
5886                         continue;
5887                 if (rtlight->corona <= 0)
5888                         continue;
5889                 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex)
5890                         continue;
5891                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
5892         }
5893         for (i = 0;i < r_refdef.scene.numlights;i++)
5894         {
5895                 rtlight = r_refdef.scene.lights[i];
5896                 rtlight->corona_visibility = 0;
5897                 rtlight->corona_queryindex_visiblepixels = 0;
5898                 rtlight->corona_queryindex_allpixels = 0;
5899                 if (!(rtlight->flags & flag))
5900                         continue;
5901                 if (rtlight->corona <= 0)
5902                         continue;
5903                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
5904         }
5905         if (usequery)
5906                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5907
5908         // now draw the coronas using the query data for intensity info
5909         for (lightindex = 0;lightindex < range;lightindex++)
5910         {
5911                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5912                 if (!light)
5913                         continue;
5914                 rtlight = &light->rtlight;
5915                 if (rtlight->corona_visibility <= 0)
5916                         continue;
5917                 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
5918         }
5919         for (i = 0;i < r_refdef.scene.numlights;i++)
5920         {
5921                 rtlight = r_refdef.scene.lights[i];
5922                 if (rtlight->corona_visibility <= 0)
5923                         continue;
5924                 if (gl_flashblend.integer)
5925                         R_DrawCorona(rtlight, rtlight->corona, rtlight->radius * rtlight->coronasizescale * 2.0f);
5926                 else
5927                         R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
5928         }
5929 }
5930
5931
5932
5933 static dlight_t *R_Shadow_NewWorldLight(void)
5934 {
5935         return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
5936 }
5937
5938 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)
5939 {
5940         matrix4x4_t matrix;
5941
5942         // 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
5943
5944         // validate parameters
5945         if (!cubemapname)
5946                 cubemapname = "";
5947
5948         // copy to light properties
5949         VectorCopy(origin, light->origin);
5950         light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
5951         light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
5952         light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
5953         /*
5954         light->color[0] = max(color[0], 0);
5955         light->color[1] = max(color[1], 0);
5956         light->color[2] = max(color[2], 0);
5957         */
5958         light->color[0] = color[0];
5959         light->color[1] = color[1];
5960         light->color[2] = color[2];
5961         light->radius = max(radius, 0);
5962         light->style = style;
5963         light->shadow = shadowenable;
5964         light->corona = corona;
5965         strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
5966         light->coronasizescale = coronasizescale;
5967         light->ambientscale = ambientscale;
5968         light->diffusescale = diffusescale;
5969         light->specularscale = specularscale;
5970         light->flags = flags;
5971
5972         // update renderable light data
5973         Matrix4x4_CreateFromQuakeEntity(&matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], light->radius);
5974         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);
5975 }
5976
5977 static void R_Shadow_FreeWorldLight(dlight_t *light)
5978 {
5979         if (r_shadow_selectedlight == light)
5980                 r_shadow_selectedlight = NULL;
5981         R_RTLight_Uncompile(&light->rtlight);
5982         Mem_ExpandableArray_FreeRecord(&r_shadow_worldlightsarray, light);
5983 }
5984
5985 void R_Shadow_ClearWorldLights(void)
5986 {
5987         size_t lightindex;
5988         dlight_t *light;
5989         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5990         for (lightindex = 0;lightindex < range;lightindex++)
5991         {
5992                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5993                 if (light)
5994                         R_Shadow_FreeWorldLight(light);
5995         }
5996         r_shadow_selectedlight = NULL;
5997 }
5998
5999 static void R_Shadow_SelectLight(dlight_t *light)
6000 {
6001         if (r_shadow_selectedlight)
6002                 r_shadow_selectedlight->selected = false;
6003         r_shadow_selectedlight = light;
6004         if (r_shadow_selectedlight)
6005                 r_shadow_selectedlight->selected = true;
6006 }
6007
6008 static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6009 {
6010         // this is never batched (there can be only one)
6011         float vertex3f[12];
6012         R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
6013         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6014         R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6015 }
6016
6017 static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6018 {
6019         float intensity;
6020         float s;
6021         vec3_t spritecolor;
6022         skinframe_t *skinframe;
6023         float vertex3f[12];
6024
6025         // this is never batched (due to the ent parameter changing every time)
6026         // so numsurfaces == 1 and surfacelist[0] == lightnumber
6027         const dlight_t *light = (dlight_t *)ent;
6028         s = EDLIGHTSPRSIZE;
6029
6030         R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
6031
6032         intensity = 0.5f;
6033         VectorScale(light->color, intensity, spritecolor);
6034         if (VectorLength(spritecolor) < 0.1732f)
6035                 VectorSet(spritecolor, 0.1f, 0.1f, 0.1f);
6036         if (VectorLength(spritecolor) > 1.0f)
6037                 VectorNormalize(spritecolor);
6038
6039         // draw light sprite
6040         if (light->cubemapname[0] && !light->shadow)
6041                 skinframe = r_editlights_sprcubemapnoshadowlight;
6042         else if (light->cubemapname[0])
6043                 skinframe = r_editlights_sprcubemaplight;
6044         else if (!light->shadow)
6045                 skinframe = r_editlights_sprnoshadowlight;
6046         else
6047                 skinframe = r_editlights_sprlight;
6048
6049         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);
6050         R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6051
6052         // draw selection sprite if light is selected
6053         if (light->selected)
6054         {
6055                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6056                 R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6057                 // VorteX todo: add normalmode/realtime mode light overlay sprites?
6058         }
6059 }
6060
6061 void R_Shadow_DrawLightSprites(void)
6062 {
6063         size_t lightindex;
6064         dlight_t *light;
6065         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6066         for (lightindex = 0;lightindex < range;lightindex++)
6067         {
6068                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6069                 if (light)
6070                         R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
6071         }
6072         if (!r_editlights_lockcursor)
6073                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
6074 }
6075
6076 int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
6077 {
6078         unsigned int range;
6079         dlight_t *light;
6080         rtlight_t *rtlight;
6081         range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
6082         if (lightindex >= range)
6083                 return -1;
6084         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6085         if (!light)
6086                 return 0;
6087         rtlight = &light->rtlight;
6088         //if (!(rtlight->flags & flag))
6089         //      return 0;
6090         VectorCopy(rtlight->shadoworigin, origin);
6091         *radius = rtlight->radius;
6092         VectorCopy(rtlight->color, color);
6093         return 1;
6094 }
6095
6096 static void R_Shadow_SelectLightInView(void)
6097 {
6098         float bestrating, rating, temp[3];
6099         dlight_t *best;
6100         size_t lightindex;
6101         dlight_t *light;
6102         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6103         best = NULL;
6104         bestrating = 0;
6105
6106         if (r_editlights_lockcursor)
6107                 return;
6108         for (lightindex = 0;lightindex < range;lightindex++)
6109         {
6110                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6111                 if (!light)
6112                         continue;
6113                 VectorSubtract(light->origin, r_refdef.view.origin, temp);
6114                 rating = (DotProduct(temp, r_refdef.view.forward) / sqrt(DotProduct(temp, temp)));
6115                 if (rating >= 0.95)
6116                 {
6117                         rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
6118                         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)
6119                         {
6120                                 bestrating = rating;
6121                                 best = light;
6122                         }
6123                 }
6124         }
6125         R_Shadow_SelectLight(best);
6126 }
6127
6128 void R_Shadow_LoadWorldLights(void)
6129 {
6130         int n, a, style, shadow, flags;
6131         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
6132         float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
6133         if (cl.worldmodel == NULL)
6134         {
6135                 Con_Print("No map loaded.\n");
6136                 return;
6137         }
6138         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6139         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6140         if (lightsstring)
6141         {
6142                 s = lightsstring;
6143                 n = 0;
6144                 while (*s)
6145                 {
6146                         /*
6147                         t = s;
6148                         shadow = true;
6149                         for (;COM_Parse(t, true) && strcmp(
6150                         if (COM_Parse(t, true))
6151                         {
6152                                 if (com_token[0] == '!')
6153                                 {
6154                                         shadow = false;
6155                                         origin[0] = atof(com_token+1);
6156                                 }
6157                                 else
6158                                         origin[0] = atof(com_token);
6159                                 if (Com_Parse(t
6160                         }
6161                         */
6162                         t = s;
6163                         while (*s && *s != '\n' && *s != '\r')
6164                                 s++;
6165                         if (!*s)
6166                                 break;
6167                         tempchar = *s;
6168                         shadow = true;
6169                         // check for modifier flags
6170                         if (*t == '!')
6171                         {
6172                                 shadow = false;
6173                                 t++;
6174                         }
6175                         *s = 0;
6176 #if _MSC_VER >= 1400
6177 #define sscanf sscanf_s
6178 #endif
6179                         cubemapname[sizeof(cubemapname)-1] = 0;
6180 #if MAX_QPATH != 128
6181 #error update this code if MAX_QPATH changes
6182 #endif
6183                         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
6184 #if _MSC_VER >= 1400
6185 , sizeof(cubemapname)
6186 #endif
6187 , &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
6188                         *s = tempchar;
6189                         if (a < 18)
6190                                 flags = LIGHTFLAG_REALTIMEMODE;
6191                         if (a < 17)
6192                                 specularscale = 1;
6193                         if (a < 16)
6194                                 diffusescale = 1;
6195                         if (a < 15)
6196                                 ambientscale = 0;
6197                         if (a < 14)
6198                                 coronasizescale = 0.25f;
6199                         if (a < 13)
6200                                 VectorClear(angles);
6201                         if (a < 10)
6202                                 corona = 0;
6203                         if (a < 9 || !strcmp(cubemapname, "\"\""))
6204                                 cubemapname[0] = 0;
6205                         // remove quotes on cubemapname
6206                         if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
6207                         {
6208                                 size_t namelen;
6209                                 namelen = strlen(cubemapname) - 2;
6210                                 memmove(cubemapname, cubemapname + 1, namelen);
6211                                 cubemapname[namelen] = '\0';
6212                         }
6213                         if (a < 8)
6214                         {
6215                                 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);
6216                                 break;
6217                         }
6218                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
6219                         if (*s == '\r')
6220                                 s++;
6221                         if (*s == '\n')
6222                                 s++;
6223                         n++;
6224                 }
6225                 if (*s)
6226                         Con_Printf("invalid rtlights file \"%s\"\n", name);
6227                 Mem_Free(lightsstring);
6228         }
6229 }
6230
6231 void R_Shadow_SaveWorldLights(void)
6232 {
6233         size_t lightindex;
6234         dlight_t *light;
6235         size_t bufchars, bufmaxchars;
6236         char *buf, *oldbuf;
6237         char name[MAX_QPATH];
6238         char line[MAX_INPUTLINE];
6239         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
6240         // I hate lines which are 3 times my screen size :( --blub
6241         if (!range)
6242                 return;
6243         if (cl.worldmodel == NULL)
6244         {
6245                 Con_Print("No map loaded.\n");
6246                 return;
6247         }
6248         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6249         bufchars = bufmaxchars = 0;
6250         buf = NULL;
6251         for (lightindex = 0;lightindex < range;lightindex++)
6252         {
6253                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6254                 if (!light)
6255                         continue;
6256                 if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE)
6257                         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);
6258                 else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
6259                         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]);
6260                 else
6261                         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);
6262                 if (bufchars + strlen(line) > bufmaxchars)
6263                 {
6264                         bufmaxchars = bufchars + strlen(line) + 2048;
6265                         oldbuf = buf;
6266                         buf = (char *)Mem_Alloc(tempmempool, bufmaxchars);
6267                         if (oldbuf)
6268                         {
6269                                 if (bufchars)
6270                                         memcpy(buf, oldbuf, bufchars);
6271                                 Mem_Free(oldbuf);
6272                         }
6273                 }
6274                 if (strlen(line))
6275                 {
6276                         memcpy(buf + bufchars, line, strlen(line));
6277                         bufchars += strlen(line);
6278                 }
6279         }
6280         if (bufchars)
6281                 FS_WriteFile(name, buf, (fs_offset_t)bufchars);
6282         if (buf)
6283                 Mem_Free(buf);
6284 }
6285
6286 void R_Shadow_LoadLightsFile(void)
6287 {
6288         int n, a, style;
6289         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
6290         float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
6291         if (cl.worldmodel == NULL)
6292         {
6293                 Con_Print("No map loaded.\n");
6294                 return;
6295         }
6296         dpsnprintf(name, sizeof(name), "%s.lights", cl.worldnamenoextension);
6297         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6298         if (lightsstring)
6299         {
6300                 s = lightsstring;
6301                 n = 0;
6302                 while (*s)
6303                 {
6304                         t = s;
6305                         while (*s && *s != '\n' && *s != '\r')
6306                                 s++;
6307                         if (!*s)
6308                                 break;
6309                         tempchar = *s;
6310                         *s = 0;
6311                         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);
6312                         *s = tempchar;
6313                         if (a < 14)
6314                         {
6315                                 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);
6316                                 break;
6317                         }
6318                         radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f));
6319                         radius = bound(15, radius, 4096);
6320                         VectorScale(color, (2.0f / (8388608.0f)), color);
6321                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6322                         if (*s == '\r')
6323                                 s++;
6324                         if (*s == '\n')
6325                                 s++;
6326                         n++;
6327                 }
6328                 if (*s)
6329                         Con_Printf("invalid lights file \"%s\"\n", name);
6330                 Mem_Free(lightsstring);
6331         }
6332 }
6333
6334 // tyrlite/hmap2 light types in the delay field
6335 typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
6336
6337 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
6338 {
6339         int entnum;
6340         int style;
6341         int islight;
6342         int skin;
6343         int pflags;
6344         //int effects;
6345         int type;
6346         int n;
6347         char *entfiledata;
6348         const char *data;
6349         float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
6350         char key[256], value[MAX_INPUTLINE];
6351         char vabuf[1024];
6352
6353         if (cl.worldmodel == NULL)
6354         {
6355                 Con_Print("No map loaded.\n");
6356                 return;
6357         }
6358         // try to load a .ent file first
6359         dpsnprintf(key, sizeof(key), "%s.ent", cl.worldnamenoextension);
6360         data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL);
6361         // and if that is not found, fall back to the bsp file entity string
6362         if (!data)
6363                 data = cl.worldmodel->brush.entities;
6364         if (!data)
6365                 return;
6366         for (entnum = 0;COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{';entnum++)
6367         {
6368                 type = LIGHTTYPE_MINUSX;
6369                 origin[0] = origin[1] = origin[2] = 0;
6370                 originhack[0] = originhack[1] = originhack[2] = 0;
6371                 angles[0] = angles[1] = angles[2] = 0;
6372                 color[0] = color[1] = color[2] = 1;
6373                 light[0] = light[1] = light[2] = 1;light[3] = 300;
6374                 overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
6375                 fadescale = 1;
6376                 lightscale = 1;
6377                 style = 0;
6378                 skin = 0;
6379                 pflags = 0;
6380                 //effects = 0;
6381                 islight = false;
6382                 while (1)
6383                 {
6384                         if (!COM_ParseToken_Simple(&data, false, false, true))
6385                                 break; // error
6386                         if (com_token[0] == '}')
6387                                 break; // end of entity
6388                         if (com_token[0] == '_')
6389                                 strlcpy(key, com_token + 1, sizeof(key));
6390                         else
6391                                 strlcpy(key, com_token, sizeof(key));
6392                         while (key[strlen(key)-1] == ' ') // remove trailing spaces
6393                                 key[strlen(key)-1] = 0;
6394                         if (!COM_ParseToken_Simple(&data, false, false, true))
6395                                 break; // error
6396                         strlcpy(value, com_token, sizeof(value));
6397
6398                         // now that we have the key pair worked out...
6399                         if (!strcmp("light", key))
6400                         {
6401                                 n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
6402                                 if (n == 1)
6403                                 {
6404                                         // quake
6405                                         light[0] = vec[0] * (1.0f / 256.0f);
6406                                         light[1] = vec[0] * (1.0f / 256.0f);
6407                                         light[2] = vec[0] * (1.0f / 256.0f);
6408                                         light[3] = vec[0];
6409                                 }
6410                                 else if (n == 4)
6411                                 {
6412                                         // halflife
6413                                         light[0] = vec[0] * (1.0f / 255.0f);
6414                                         light[1] = vec[1] * (1.0f / 255.0f);
6415                                         light[2] = vec[2] * (1.0f / 255.0f);
6416                                         light[3] = vec[3];
6417                                 }
6418                         }
6419                         else if (!strcmp("delay", key))
6420                                 type = atoi(value);
6421                         else if (!strcmp("origin", key))
6422                                 sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
6423                         else if (!strcmp("angle", key))
6424                                 angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
6425                         else if (!strcmp("angles", key))
6426                                 sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
6427                         else if (!strcmp("color", key))
6428                                 sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
6429                         else if (!strcmp("wait", key))
6430                                 fadescale = atof(value);
6431                         else if (!strcmp("classname", key))
6432                         {
6433                                 if (!strncmp(value, "light", 5))
6434                                 {
6435                                         islight = true;
6436                                         if (!strcmp(value, "light_fluoro"))
6437                                         {
6438                                                 originhack[0] = 0;
6439                                                 originhack[1] = 0;
6440                                                 originhack[2] = 0;
6441                                                 overridecolor[0] = 1;
6442                                                 overridecolor[1] = 1;
6443                                                 overridecolor[2] = 1;
6444                                         }
6445                                         if (!strcmp(value, "light_fluorospark"))
6446                                         {
6447                                                 originhack[0] = 0;
6448                                                 originhack[1] = 0;
6449                                                 originhack[2] = 0;
6450                                                 overridecolor[0] = 1;
6451                                                 overridecolor[1] = 1;
6452                                                 overridecolor[2] = 1;
6453                                         }
6454                                         if (!strcmp(value, "light_globe"))
6455                                         {
6456                                                 originhack[0] = 0;
6457                                                 originhack[1] = 0;
6458                                                 originhack[2] = 0;
6459                                                 overridecolor[0] = 1;
6460                                                 overridecolor[1] = 0.8;
6461                                                 overridecolor[2] = 0.4;
6462                                         }
6463                                         if (!strcmp(value, "light_flame_large_yellow"))
6464                                         {
6465                                                 originhack[0] = 0;
6466                                                 originhack[1] = 0;
6467                                                 originhack[2] = 0;
6468                                                 overridecolor[0] = 1;
6469                                                 overridecolor[1] = 0.5;
6470                                                 overridecolor[2] = 0.1;
6471                                         }
6472                                         if (!strcmp(value, "light_flame_small_yellow"))
6473                                         {
6474                                                 originhack[0] = 0;
6475                                                 originhack[1] = 0;
6476                                                 originhack[2] = 0;
6477                                                 overridecolor[0] = 1;
6478                                                 overridecolor[1] = 0.5;
6479                                                 overridecolor[2] = 0.1;
6480                                         }
6481                                         if (!strcmp(value, "light_torch_small_white"))
6482                                         {
6483                                                 originhack[0] = 0;
6484                                                 originhack[1] = 0;
6485                                                 originhack[2] = 0;
6486                                                 overridecolor[0] = 1;
6487                                                 overridecolor[1] = 0.5;
6488                                                 overridecolor[2] = 0.1;
6489                                         }
6490                                         if (!strcmp(value, "light_torch_small_walltorch"))
6491                                         {
6492                                                 originhack[0] = 0;
6493                                                 originhack[1] = 0;
6494                                                 originhack[2] = 0;
6495                                                 overridecolor[0] = 1;
6496                                                 overridecolor[1] = 0.5;
6497                                                 overridecolor[2] = 0.1;
6498                                         }
6499                                 }
6500                         }
6501                         else if (!strcmp("style", key))
6502                                 style = atoi(value);
6503                         else if (!strcmp("skin", key))
6504                                 skin = (int)atof(value);
6505                         else if (!strcmp("pflags", key))
6506                                 pflags = (int)atof(value);
6507                         //else if (!strcmp("effects", key))
6508                         //      effects = (int)atof(value);
6509                         else if (cl.worldmodel->type == mod_brushq3)
6510                         {
6511                                 if (!strcmp("scale", key))
6512                                         lightscale = atof(value);
6513                                 if (!strcmp("fade", key))
6514                                         fadescale = atof(value);
6515                         }
6516                 }
6517                 if (!islight)
6518                         continue;
6519                 if (lightscale <= 0)
6520                         lightscale = 1;
6521                 if (fadescale <= 0)
6522                         fadescale = 1;
6523                 if (color[0] == color[1] && color[0] == color[2])
6524                 {
6525                         color[0] *= overridecolor[0];
6526                         color[1] *= overridecolor[1];
6527                         color[2] *= overridecolor[2];
6528                 }
6529                 radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
6530                 color[0] = color[0] * light[0];
6531                 color[1] = color[1] * light[1];
6532                 color[2] = color[2] * light[2];
6533                 switch (type)
6534                 {
6535                 case LIGHTTYPE_MINUSX:
6536                         break;
6537                 case LIGHTTYPE_RECIPX:
6538                         radius *= 2;
6539                         VectorScale(color, (1.0f / 16.0f), color);
6540                         break;
6541                 case LIGHTTYPE_RECIPXX:
6542                         radius *= 2;
6543                         VectorScale(color, (1.0f / 16.0f), color);
6544                         break;
6545                 default:
6546                 case LIGHTTYPE_NONE:
6547                         break;
6548                 case LIGHTTYPE_SUN:
6549                         break;
6550                 case LIGHTTYPE_MINUSXX:
6551                         break;
6552                 }
6553                 VectorAdd(origin, originhack, origin);
6554                 if (radius >= 1)
6555                         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);
6556         }
6557         if (entfiledata)
6558                 Mem_Free(entfiledata);
6559 }
6560
6561
6562 static void R_Shadow_SetCursorLocationForView(void)
6563 {
6564         vec_t dist, push;
6565         vec3_t dest, endpos;
6566         trace_t trace;
6567         VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
6568         trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true);
6569         if (trace.fraction < 1)
6570         {
6571                 dist = trace.fraction * r_editlights_cursordistance.value;
6572                 push = r_editlights_cursorpushback.value;
6573                 if (push > dist)
6574                         push = dist;
6575                 push = -push;
6576                 VectorMA(trace.endpos, push, r_refdef.view.forward, endpos);
6577                 VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
6578         }
6579         else
6580         {
6581                 VectorClear( endpos );
6582         }
6583         r_editlights_cursorlocation[0] = floor(endpos[0] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6584         r_editlights_cursorlocation[1] = floor(endpos[1] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6585         r_editlights_cursorlocation[2] = floor(endpos[2] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6586 }
6587
6588 void R_Shadow_UpdateWorldLightSelection(void)
6589 {
6590         if (r_editlights.integer)
6591         {
6592                 R_Shadow_SetCursorLocationForView();
6593                 R_Shadow_SelectLightInView();
6594         }
6595         else
6596                 R_Shadow_SelectLight(NULL);
6597 }
6598
6599 static void R_Shadow_EditLights_Clear_f(void)
6600 {
6601         R_Shadow_ClearWorldLights();
6602 }
6603
6604 void R_Shadow_EditLights_Reload_f(void)
6605 {
6606         if (!cl.worldmodel)
6607                 return;
6608         strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname));
6609         R_Shadow_ClearWorldLights();
6610         if (r_shadow_realtime_world_importlightentitiesfrommap.integer <= 1)
6611         {
6612                 R_Shadow_LoadWorldLights();
6613                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6614                         R_Shadow_LoadLightsFile();
6615         }
6616         if (r_shadow_realtime_world_importlightentitiesfrommap.integer >= 1)
6617         {
6618                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6619                         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6620         }
6621 }
6622
6623 static void R_Shadow_EditLights_Save_f(void)
6624 {
6625         if (!cl.worldmodel)
6626                 return;
6627         R_Shadow_SaveWorldLights();
6628 }
6629
6630 static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
6631 {
6632         R_Shadow_ClearWorldLights();
6633         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6634 }
6635
6636 static void R_Shadow_EditLights_ImportLightsFile_f(void)
6637 {
6638         R_Shadow_ClearWorldLights();
6639         R_Shadow_LoadLightsFile();
6640 }
6641
6642 static void R_Shadow_EditLights_Spawn_f(void)
6643 {
6644         vec3_t color;
6645         if (!r_editlights.integer)
6646         {
6647                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6648                 return;
6649         }
6650         if (Cmd_Argc() != 1)
6651         {
6652                 Con_Print("r_editlights_spawn does not take parameters\n");
6653                 return;
6654         }
6655         color[0] = color[1] = color[2] = 1;
6656         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6657 }
6658
6659 static void R_Shadow_EditLights_Edit_f(void)
6660 {
6661         vec3_t origin, angles, color;
6662         vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
6663         int style, shadows, flags, normalmode, realtimemode;
6664         char cubemapname[MAX_INPUTLINE];
6665         if (!r_editlights.integer)
6666         {
6667                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6668                 return;
6669         }
6670         if (!r_shadow_selectedlight)
6671         {
6672                 Con_Print("No selected light.\n");
6673                 return;
6674         }
6675         VectorCopy(r_shadow_selectedlight->origin, origin);
6676         VectorCopy(r_shadow_selectedlight->angles, angles);
6677         VectorCopy(r_shadow_selectedlight->color, color);
6678         radius = r_shadow_selectedlight->radius;
6679         style = r_shadow_selectedlight->style;
6680         if (r_shadow_selectedlight->cubemapname)
6681                 strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
6682         else
6683                 cubemapname[0] = 0;
6684         shadows = r_shadow_selectedlight->shadow;
6685         corona = r_shadow_selectedlight->corona;
6686         coronasizescale = r_shadow_selectedlight->coronasizescale;
6687         ambientscale = r_shadow_selectedlight->ambientscale;
6688         diffusescale = r_shadow_selectedlight->diffusescale;
6689         specularscale = r_shadow_selectedlight->specularscale;
6690         flags = r_shadow_selectedlight->flags;
6691         normalmode = (flags & LIGHTFLAG_NORMALMODE) != 0;
6692         realtimemode = (flags & LIGHTFLAG_REALTIMEMODE) != 0;
6693         if (!strcmp(Cmd_Argv(1), "origin"))
6694         {
6695                 if (Cmd_Argc() != 5)
6696                 {
6697                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6698                         return;
6699                 }
6700                 origin[0] = atof(Cmd_Argv(2));
6701                 origin[1] = atof(Cmd_Argv(3));
6702                 origin[2] = atof(Cmd_Argv(4));
6703         }
6704         else if (!strcmp(Cmd_Argv(1), "originscale"))
6705         {
6706                 if (Cmd_Argc() != 5)
6707                 {
6708                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6709                         return;
6710                 }
6711                 origin[0] *= atof(Cmd_Argv(2));
6712                 origin[1] *= atof(Cmd_Argv(3));
6713                 origin[2] *= atof(Cmd_Argv(4));
6714         }
6715         else if (!strcmp(Cmd_Argv(1), "originx"))
6716         {
6717                 if (Cmd_Argc() != 3)
6718                 {
6719                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6720                         return;
6721                 }
6722                 origin[0] = atof(Cmd_Argv(2));
6723         }
6724         else if (!strcmp(Cmd_Argv(1), "originy"))
6725         {
6726                 if (Cmd_Argc() != 3)
6727                 {
6728                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6729                         return;
6730                 }
6731                 origin[1] = atof(Cmd_Argv(2));
6732         }
6733         else if (!strcmp(Cmd_Argv(1), "originz"))
6734         {
6735                 if (Cmd_Argc() != 3)
6736                 {
6737                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6738                         return;
6739                 }
6740                 origin[2] = atof(Cmd_Argv(2));
6741         }
6742         else if (!strcmp(Cmd_Argv(1), "move"))
6743         {
6744                 if (Cmd_Argc() != 5)
6745                 {
6746                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6747                         return;
6748                 }
6749                 origin[0] += atof(Cmd_Argv(2));
6750                 origin[1] += atof(Cmd_Argv(3));
6751                 origin[2] += atof(Cmd_Argv(4));
6752         }
6753         else if (!strcmp(Cmd_Argv(1), "movex"))
6754         {
6755                 if (Cmd_Argc() != 3)
6756                 {
6757                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6758                         return;
6759                 }
6760                 origin[0] += atof(Cmd_Argv(2));
6761         }
6762         else if (!strcmp(Cmd_Argv(1), "movey"))
6763         {
6764                 if (Cmd_Argc() != 3)
6765                 {
6766                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6767                         return;
6768                 }
6769                 origin[1] += atof(Cmd_Argv(2));
6770         }
6771         else if (!strcmp(Cmd_Argv(1), "movez"))
6772         {
6773                 if (Cmd_Argc() != 3)
6774                 {
6775                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6776                         return;
6777                 }
6778                 origin[2] += atof(Cmd_Argv(2));
6779         }
6780         else if (!strcmp(Cmd_Argv(1), "angles"))
6781         {
6782                 if (Cmd_Argc() != 5)
6783                 {
6784                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6785                         return;
6786                 }
6787                 angles[0] = atof(Cmd_Argv(2));
6788                 angles[1] = atof(Cmd_Argv(3));
6789                 angles[2] = atof(Cmd_Argv(4));
6790         }
6791         else if (!strcmp(Cmd_Argv(1), "anglesx"))
6792         {
6793                 if (Cmd_Argc() != 3)
6794                 {
6795                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6796                         return;
6797                 }
6798                 angles[0] = atof(Cmd_Argv(2));
6799         }
6800         else if (!strcmp(Cmd_Argv(1), "anglesy"))
6801         {
6802                 if (Cmd_Argc() != 3)
6803                 {
6804                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6805                         return;
6806                 }
6807                 angles[1] = atof(Cmd_Argv(2));
6808         }
6809         else if (!strcmp(Cmd_Argv(1), "anglesz"))
6810         {
6811                 if (Cmd_Argc() != 3)
6812                 {
6813                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6814                         return;
6815                 }
6816                 angles[2] = atof(Cmd_Argv(2));
6817         }
6818         else if (!strcmp(Cmd_Argv(1), "color"))
6819         {
6820                 if (Cmd_Argc() != 5)
6821                 {
6822                         Con_Printf("usage: r_editlights_edit %s red green blue\n", Cmd_Argv(1));
6823                         return;
6824                 }
6825                 color[0] = atof(Cmd_Argv(2));
6826                 color[1] = atof(Cmd_Argv(3));
6827                 color[2] = atof(Cmd_Argv(4));
6828         }
6829         else if (!strcmp(Cmd_Argv(1), "radius"))
6830         {
6831                 if (Cmd_Argc() != 3)
6832                 {
6833                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6834                         return;
6835                 }
6836                 radius = atof(Cmd_Argv(2));
6837         }
6838         else if (!strcmp(Cmd_Argv(1), "colorscale"))
6839         {
6840                 if (Cmd_Argc() == 3)
6841                 {
6842                         double scale = atof(Cmd_Argv(2));
6843                         color[0] *= scale;
6844                         color[1] *= scale;
6845                         color[2] *= scale;
6846                 }
6847                 else
6848                 {
6849                         if (Cmd_Argc() != 5)
6850                         {
6851                                 Con_Printf("usage: r_editlights_edit %s red green blue  (OR grey instead of red green blue)\n", Cmd_Argv(1));
6852                                 return;
6853                         }
6854                         color[0] *= atof(Cmd_Argv(2));
6855                         color[1] *= atof(Cmd_Argv(3));
6856                         color[2] *= atof(Cmd_Argv(4));
6857                 }
6858         }
6859         else if (!strcmp(Cmd_Argv(1), "radiusscale") || !strcmp(Cmd_Argv(1), "sizescale"))
6860         {
6861                 if (Cmd_Argc() != 3)
6862                 {
6863                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6864                         return;
6865                 }
6866                 radius *= atof(Cmd_Argv(2));
6867         }
6868         else if (!strcmp(Cmd_Argv(1), "style"))
6869         {
6870                 if (Cmd_Argc() != 3)
6871                 {
6872                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6873                         return;
6874                 }
6875                 style = atoi(Cmd_Argv(2));
6876         }
6877         else if (!strcmp(Cmd_Argv(1), "cubemap"))
6878         {
6879                 if (Cmd_Argc() > 3)
6880                 {
6881                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6882                         return;
6883                 }
6884                 if (Cmd_Argc() == 3)
6885                         strlcpy(cubemapname, Cmd_Argv(2), sizeof(cubemapname));
6886                 else
6887                         cubemapname[0] = 0;
6888         }
6889         else if (!strcmp(Cmd_Argv(1), "shadows"))
6890         {
6891                 if (Cmd_Argc() != 3)
6892                 {
6893                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6894                         return;
6895                 }
6896                 shadows = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
6897         }
6898         else if (!strcmp(Cmd_Argv(1), "corona"))
6899         {
6900                 if (Cmd_Argc() != 3)
6901                 {
6902                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6903                         return;
6904                 }
6905                 corona = atof(Cmd_Argv(2));
6906         }
6907         else if (!strcmp(Cmd_Argv(1), "coronasize"))
6908         {
6909                 if (Cmd_Argc() != 3)
6910                 {
6911                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6912                         return;
6913                 }
6914                 coronasizescale = atof(Cmd_Argv(2));
6915         }
6916         else if (!strcmp(Cmd_Argv(1), "ambient"))
6917         {
6918                 if (Cmd_Argc() != 3)
6919                 {
6920                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6921                         return;
6922                 }
6923                 ambientscale = atof(Cmd_Argv(2));
6924         }
6925         else if (!strcmp(Cmd_Argv(1), "diffuse"))
6926         {
6927                 if (Cmd_Argc() != 3)
6928                 {
6929                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6930                         return;
6931                 }
6932                 diffusescale = atof(Cmd_Argv(2));
6933         }
6934         else if (!strcmp(Cmd_Argv(1), "specular"))
6935         {
6936                 if (Cmd_Argc() != 3)
6937                 {
6938                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6939                         return;
6940                 }
6941                 specularscale = atof(Cmd_Argv(2));
6942         }
6943         else if (!strcmp(Cmd_Argv(1), "normalmode"))
6944         {
6945                 if (Cmd_Argc() != 3)
6946                 {
6947                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6948                         return;
6949                 }
6950                 normalmode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
6951         }
6952         else if (!strcmp(Cmd_Argv(1), "realtimemode"))
6953         {
6954                 if (Cmd_Argc() != 3)
6955                 {
6956                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6957                         return;
6958                 }
6959                 realtimemode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
6960         }
6961         else
6962         {
6963                 Con_Print("usage: r_editlights_edit [property] [value]\n");
6964                 Con_Print("Selected light's properties:\n");
6965                 Con_Printf("Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
6966                 Con_Printf("Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
6967                 Con_Printf("Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
6968                 Con_Printf("Radius       : %f\n", r_shadow_selectedlight->radius);
6969                 Con_Printf("Corona       : %f\n", r_shadow_selectedlight->corona);
6970                 Con_Printf("Style        : %i\n", r_shadow_selectedlight->style);
6971                 Con_Printf("Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
6972                 Con_Printf("Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);
6973                 Con_Printf("CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);
6974                 Con_Printf("Ambient      : %f\n", r_shadow_selectedlight->ambientscale);
6975                 Con_Printf("Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);
6976                 Con_Printf("Specular     : %f\n", r_shadow_selectedlight->specularscale);
6977                 Con_Printf("NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");
6978                 Con_Printf("RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");
6979                 return;
6980         }
6981         flags = (normalmode ? LIGHTFLAG_NORMALMODE : 0) | (realtimemode ? LIGHTFLAG_REALTIMEMODE : 0);
6982         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
6983 }
6984
6985 static void R_Shadow_EditLights_EditAll_f(void)
6986 {
6987         size_t lightindex;
6988         dlight_t *light, *oldselected;
6989         size_t range;
6990
6991         if (!r_editlights.integer)
6992         {
6993                 Con_Print("Cannot edit lights when not in editing mode. Set r_editlights to 1.\n");
6994                 return;
6995         }
6996
6997         oldselected = r_shadow_selectedlight;
6998         // EditLights doesn't seem to have a "remove" command or something so:
6999         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7000         for (lightindex = 0;lightindex < range;lightindex++)
7001         {
7002                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7003                 if (!light)
7004                         continue;
7005                 R_Shadow_SelectLight(light);
7006                 R_Shadow_EditLights_Edit_f();
7007         }
7008         // return to old selected (to not mess editing once selection is locked)
7009         R_Shadow_SelectLight(oldselected);
7010 }
7011
7012 void R_Shadow_EditLights_DrawSelectedLightProperties(void)
7013 {
7014         int lightnumber, lightcount;
7015         size_t lightindex, range;
7016         dlight_t *light;
7017         char temp[256];
7018         float x, y;
7019
7020         if (!r_editlights.integer)
7021                 return;
7022
7023         // update cvars so QC can query them
7024         if (r_shadow_selectedlight)
7025         {
7026                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
7027                 Cvar_SetQuick(&r_editlights_current_origin, temp);
7028                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
7029                 Cvar_SetQuick(&r_editlights_current_angles, temp);
7030                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
7031                 Cvar_SetQuick(&r_editlights_current_color, temp);
7032                 Cvar_SetValueQuick(&r_editlights_current_radius, r_shadow_selectedlight->radius);
7033                 Cvar_SetValueQuick(&r_editlights_current_corona, r_shadow_selectedlight->corona);
7034                 Cvar_SetValueQuick(&r_editlights_current_coronasize, r_shadow_selectedlight->coronasizescale);
7035                 Cvar_SetValueQuick(&r_editlights_current_style, r_shadow_selectedlight->style);
7036                 Cvar_SetValueQuick(&r_editlights_current_shadows, r_shadow_selectedlight->shadow);
7037                 Cvar_SetQuick(&r_editlights_current_cubemap, r_shadow_selectedlight->cubemapname);
7038                 Cvar_SetValueQuick(&r_editlights_current_ambient, r_shadow_selectedlight->ambientscale);
7039                 Cvar_SetValueQuick(&r_editlights_current_diffuse, r_shadow_selectedlight->diffusescale);
7040                 Cvar_SetValueQuick(&r_editlights_current_specular, r_shadow_selectedlight->specularscale);
7041                 Cvar_SetValueQuick(&r_editlights_current_normalmode, (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? 1 : 0);
7042                 Cvar_SetValueQuick(&r_editlights_current_realtimemode, (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? 1 : 0);
7043         }
7044
7045         // draw properties on screen
7046         if (!r_editlights_drawproperties.integer)
7047                 return;
7048         x = vid_conwidth.value - 240;
7049         y = 5;
7050         DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
7051         lightnumber = -1;
7052         lightcount = 0;
7053         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7054         for (lightindex = 0;lightindex < range;lightindex++)
7055         {
7056                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7057                 if (!light)
7058                         continue;
7059                 if (light == r_shadow_selectedlight)
7060                         lightnumber = (int)lightindex;
7061                 lightcount++;
7062         }
7063         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;
7064         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;
7065         y += 8;
7066         if (r_shadow_selectedlight == NULL)
7067                 return;
7068         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;
7069         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;
7070         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;
7071         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;
7072         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;
7073         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;
7074         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;
7075         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;
7076         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;
7077         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;
7078         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;
7079         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;
7080         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;
7081         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;
7082         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;
7083 }
7084
7085 static void R_Shadow_EditLights_ToggleShadow_f(void)
7086 {
7087         if (!r_editlights.integer)
7088         {
7089                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7090                 return;
7091         }
7092         if (!r_shadow_selectedlight)
7093         {
7094                 Con_Print("No selected light.\n");
7095                 return;
7096         }
7097         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);
7098 }
7099
7100 static void R_Shadow_EditLights_ToggleCorona_f(void)
7101 {
7102         if (!r_editlights.integer)
7103         {
7104                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7105                 return;
7106         }
7107         if (!r_shadow_selectedlight)
7108         {
7109                 Con_Print("No selected light.\n");
7110                 return;
7111         }
7112         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);
7113 }
7114
7115 static void R_Shadow_EditLights_Remove_f(void)
7116 {
7117         if (!r_editlights.integer)
7118         {
7119                 Con_Print("Cannot remove light when not in editing mode.  Set r_editlights to 1.\n");
7120                 return;
7121         }
7122         if (!r_shadow_selectedlight)
7123         {
7124                 Con_Print("No selected light.\n");
7125                 return;
7126         }
7127         R_Shadow_FreeWorldLight(r_shadow_selectedlight);
7128         r_shadow_selectedlight = NULL;
7129 }
7130
7131 static void R_Shadow_EditLights_Help_f(void)
7132 {
7133         Con_Print(
7134 "Documentation on r_editlights system:\n"
7135 "Settings:\n"
7136 "r_editlights : enable/disable editing mode\n"
7137 "r_editlights_cursordistance : maximum distance of cursor from eye\n"
7138 "r_editlights_cursorpushback : push back cursor this far from surface\n"
7139 "r_editlights_cursorpushoff : push cursor off surface this far\n"
7140 "r_editlights_cursorgrid : snap cursor to grid of this size\n"
7141 "r_editlights_quakelightsizescale : imported quake light entity size scaling\n"
7142 "Commands:\n"
7143 "r_editlights_help : this help\n"
7144 "r_editlights_clear : remove all lights\n"
7145 "r_editlights_reload : reload .rtlights, .lights file, or entities\n"
7146 "r_editlights_lock : lock selection to current light, if already locked - unlock\n"
7147 "r_editlights_save : save to .rtlights file\n"
7148 "r_editlights_spawn : create a light with default settings\n"
7149 "r_editlights_edit command : edit selected light - more documentation below\n"
7150 "r_editlights_remove : remove selected light\n"
7151 "r_editlights_toggleshadow : toggles on/off selected light's shadow property\n"
7152 "r_editlights_importlightentitiesfrommap : reload light entities\n"
7153 "r_editlights_importlightsfile : reload .light file (produced by hlight)\n"
7154 "Edit commands:\n"
7155 "origin x y z : set light location\n"
7156 "originx x: set x component of light location\n"
7157 "originy y: set y component of light location\n"
7158 "originz z: set z component of light location\n"
7159 "move x y z : adjust light location\n"
7160 "movex x: adjust x component of light location\n"
7161 "movey y: adjust y component of light location\n"
7162 "movez z: adjust z component of light location\n"
7163 "angles x y z : set light angles\n"
7164 "anglesx x: set x component of light angles\n"
7165 "anglesy y: set y component of light angles\n"
7166 "anglesz z: set z component of light angles\n"
7167 "color r g b : set color of light (can be brighter than 1 1 1)\n"
7168 "radius radius : set radius (size) of light\n"
7169 "colorscale grey : multiply color of light (1 does nothing)\n"
7170 "colorscale r g b : multiply color of light (1 1 1 does nothing)\n"
7171 "radiusscale scale : multiply radius (size) of light (1 does nothing)\n"
7172 "sizescale scale : multiply radius (size) of light (1 does nothing)\n"
7173 "originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
7174 "style style : set lightstyle of light (flickering patterns, switches, etc)\n"
7175 "cubemap basename : set filter cubemap of light\n"
7176 "shadows 1/0 : turn on/off shadows\n"
7177 "corona n : set corona intensity\n"
7178 "coronasize n : set corona size (0-1)\n"
7179 "ambient n : set ambient intensity (0-1)\n"
7180 "diffuse n : set diffuse intensity (0-1)\n"
7181 "specular n : set specular intensity (0-1)\n"
7182 "normalmode 1/0 : turn on/off rendering of this light in rtworld 0 mode\n"
7183 "realtimemode 1/0 : turn on/off rendering of this light in rtworld 1 mode\n"
7184 "<nothing> : print light properties to console\n"
7185         );
7186 }
7187
7188 static void R_Shadow_EditLights_CopyInfo_f(void)
7189 {
7190         if (!r_editlights.integer)
7191         {
7192                 Con_Print("Cannot copy light info when not in editing mode.  Set r_editlights to 1.\n");
7193                 return;
7194         }
7195         if (!r_shadow_selectedlight)
7196         {
7197                 Con_Print("No selected light.\n");
7198                 return;
7199         }
7200         VectorCopy(r_shadow_selectedlight->angles, r_shadow_bufferlight.angles);
7201         VectorCopy(r_shadow_selectedlight->color, r_shadow_bufferlight.color);
7202         r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
7203         r_shadow_bufferlight.style = r_shadow_selectedlight->style;
7204         if (r_shadow_selectedlight->cubemapname)
7205                 strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
7206         else
7207                 r_shadow_bufferlight.cubemapname[0] = 0;
7208         r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;
7209         r_shadow_bufferlight.corona = r_shadow_selectedlight->corona;
7210         r_shadow_bufferlight.coronasizescale = r_shadow_selectedlight->coronasizescale;
7211         r_shadow_bufferlight.ambientscale = r_shadow_selectedlight->ambientscale;
7212         r_shadow_bufferlight.diffusescale = r_shadow_selectedlight->diffusescale;
7213         r_shadow_bufferlight.specularscale = r_shadow_selectedlight->specularscale;
7214         r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
7215 }
7216
7217 static void R_Shadow_EditLights_PasteInfo_f(void)
7218 {
7219         if (!r_editlights.integer)
7220         {
7221                 Con_Print("Cannot paste light info when not in editing mode.  Set r_editlights to 1.\n");
7222                 return;
7223         }
7224         if (!r_shadow_selectedlight)
7225         {
7226                 Con_Print("No selected light.\n");
7227                 return;
7228         }
7229         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);
7230 }
7231
7232 static void R_Shadow_EditLights_Lock_f(void)
7233 {
7234         if (!r_editlights.integer)
7235         {
7236                 Con_Print("Cannot lock on light when not in editing mode.  Set r_editlights to 1.\n");
7237                 return;
7238         }
7239         if (r_editlights_lockcursor)
7240         {
7241                 r_editlights_lockcursor = false;
7242                 return;
7243         }
7244         if (!r_shadow_selectedlight)
7245         {
7246                 Con_Print("No selected light to lock on.\n");
7247                 return;
7248         }
7249         r_editlights_lockcursor = true;
7250 }
7251
7252 static void R_Shadow_EditLights_Init(void)
7253 {
7254         Cvar_RegisterVariable(&r_editlights);
7255         Cvar_RegisterVariable(&r_editlights_cursordistance);
7256         Cvar_RegisterVariable(&r_editlights_cursorpushback);
7257         Cvar_RegisterVariable(&r_editlights_cursorpushoff);
7258         Cvar_RegisterVariable(&r_editlights_cursorgrid);
7259         Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
7260         Cvar_RegisterVariable(&r_editlights_drawproperties);
7261         Cvar_RegisterVariable(&r_editlights_current_origin);
7262         Cvar_RegisterVariable(&r_editlights_current_angles);
7263         Cvar_RegisterVariable(&r_editlights_current_color);
7264         Cvar_RegisterVariable(&r_editlights_current_radius);
7265         Cvar_RegisterVariable(&r_editlights_current_corona);
7266         Cvar_RegisterVariable(&r_editlights_current_coronasize);
7267         Cvar_RegisterVariable(&r_editlights_current_style);
7268         Cvar_RegisterVariable(&r_editlights_current_shadows);
7269         Cvar_RegisterVariable(&r_editlights_current_cubemap);
7270         Cvar_RegisterVariable(&r_editlights_current_ambient);
7271         Cvar_RegisterVariable(&r_editlights_current_diffuse);
7272         Cvar_RegisterVariable(&r_editlights_current_specular);
7273         Cvar_RegisterVariable(&r_editlights_current_normalmode);
7274         Cvar_RegisterVariable(&r_editlights_current_realtimemode);
7275         Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
7276         Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
7277         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)");
7278         Cmd_AddCommand("r_editlights_save", R_Shadow_EditLights_Save_f, "save .rtlights file for current level");
7279         Cmd_AddCommand("r_editlights_spawn", R_Shadow_EditLights_Spawn_f, "creates a light with default properties (let there be light!)");
7280         Cmd_AddCommand("r_editlights_edit", R_Shadow_EditLights_Edit_f, "changes a property on the selected light");
7281         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)");
7282         Cmd_AddCommand("r_editlights_remove", R_Shadow_EditLights_Remove_f, "remove selected light");
7283         Cmd_AddCommand("r_editlights_toggleshadow", R_Shadow_EditLights_ToggleShadow_f, "toggle on/off the shadow option on the selected light");
7284         Cmd_AddCommand("r_editlights_togglecorona", R_Shadow_EditLights_ToggleCorona_f, "toggle on/off the corona option on the selected light");
7285         Cmd_AddCommand("r_editlights_importlightentitiesfrommap", R_Shadow_EditLights_ImportLightEntitiesFromMap_f, "load lights from .ent file or map entities (ignoring .rtlights or .lights file)");
7286         Cmd_AddCommand("r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)");
7287         Cmd_AddCommand("r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
7288         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)");
7289         Cmd_AddCommand("r_editlights_lock", R_Shadow_EditLights_Lock_f, "lock selection to current light, if already locked - unlock");
7290 }
7291
7292
7293
7294 /*
7295 =============================================================================
7296
7297 LIGHT SAMPLING
7298
7299 =============================================================================
7300 */
7301
7302 void R_LightPoint(float *color, const vec3_t p, const int flags)
7303 {
7304         int i, numlights, flag;
7305         float f, relativepoint[3], dist, dist2, lightradius2;
7306         vec3_t diffuse, n;
7307         rtlight_t *light;
7308         dlight_t *dlight;
7309
7310         if (r_fullbright.integer)
7311         {
7312                 VectorSet(color, 1, 1, 1);
7313                 return;
7314         }
7315
7316         VectorClear(color);
7317
7318         if (flags & LP_LIGHTMAP)
7319         {
7320                 if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7321                 {
7322                         VectorClear(diffuse);
7323                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, color, diffuse, n);
7324                         VectorAdd(color, diffuse, color);
7325                 }
7326                 else
7327                         VectorSet(color, 1, 1, 1);
7328                 color[0] += r_refdef.scene.ambient;
7329                 color[1] += r_refdef.scene.ambient;
7330                 color[2] += r_refdef.scene.ambient;
7331         }
7332
7333         if (flags & LP_RTWORLD)
7334         {
7335                 flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
7336                 numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
7337                 for (i = 0; i < numlights; i++)
7338                 {
7339                         dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
7340                         if (!dlight)
7341                                 continue;
7342                         light = &dlight->rtlight;
7343                         if (!(light->flags & flag))
7344                                 continue;
7345                         // sample
7346                         lightradius2 = light->radius * light->radius;
7347                         VectorSubtract(light->shadoworigin, p, relativepoint);
7348                         dist2 = VectorLength2(relativepoint);
7349                         if (dist2 >= lightradius2)
7350                                 continue;
7351                         dist = sqrt(dist2) / light->radius;
7352                         f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
7353                         if (f <= 0)
7354                                 continue;
7355                         // todo: add to both ambient and diffuse
7356                         if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
7357                                 VectorMA(color, f, light->currentcolor, color);
7358                 }
7359         }
7360         if (flags & LP_DYNLIGHT)
7361         {
7362                 // sample dlights
7363                 for (i = 0;i < r_refdef.scene.numlights;i++)
7364                 {
7365                         light = r_refdef.scene.lights[i];
7366                         // sample
7367                         lightradius2 = light->radius * light->radius;
7368                         VectorSubtract(light->shadoworigin, p, relativepoint);
7369                         dist2 = VectorLength2(relativepoint);
7370                         if (dist2 >= lightradius2)
7371                                 continue;
7372                         dist = sqrt(dist2) / light->radius;
7373                         f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
7374                         if (f <= 0)
7375                                 continue;
7376                         // todo: add to both ambient and diffuse
7377                         if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
7378                                 VectorMA(color, f, light->color, color);
7379                 }
7380         }
7381 }
7382
7383 void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const vec3_t p, const int flags)
7384 {
7385         int i, numlights, flag;
7386         rtlight_t *light;
7387         dlight_t *dlight;
7388         float relativepoint[3];
7389         float color[3];
7390         float dir[3];
7391         float dist;
7392         float dist2;
7393         float intensity;
7394         float sample[5*3];
7395         float lightradius2;
7396
7397         if (r_fullbright.integer)
7398         {
7399                 VectorSet(ambient, 1, 1, 1);
7400                 VectorClear(diffuse);
7401                 VectorClear(lightdir);
7402                 return;
7403         }
7404
7405         if (flags == LP_LIGHTMAP)
7406         {
7407                 VectorSet(ambient, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
7408                 VectorClear(diffuse);
7409                 VectorClear(lightdir);
7410                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7411                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambient, diffuse, lightdir);
7412                 else
7413                         VectorSet(ambient, 1, 1, 1);
7414                 return;
7415         }
7416
7417         memset(sample, 0, sizeof(sample));
7418         VectorSet(sample, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
7419
7420         if ((flags & LP_LIGHTMAP) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7421         {
7422                 vec3_t tempambient;
7423                 VectorClear(tempambient);
7424                 VectorClear(color);
7425                 VectorClear(relativepoint);
7426                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
7427                 VectorScale(tempambient, r_refdef.lightmapintensity, tempambient);
7428                 VectorScale(color, r_refdef.lightmapintensity, color);
7429                 VectorAdd(sample, tempambient, sample);
7430                 VectorMA(sample    , 0.5f            , color, sample    );
7431                 VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7432                 VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7433                 VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7434                 // calculate a weighted average light direction as well
7435                 intensity = VectorLength(color);
7436                 VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7437         }
7438
7439         if (flags & LP_RTWORLD)
7440         {
7441                 flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
7442                 numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
7443                 for (i = 0; i < numlights; i++)
7444                 {
7445                         dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
7446                         if (!dlight)
7447                                 continue;
7448                         light = &dlight->rtlight;
7449                         if (!(light->flags & flag))
7450                                 continue;
7451                         // sample
7452                         lightradius2 = light->radius * light->radius;
7453                         VectorSubtract(light->shadoworigin, p, relativepoint);
7454                         dist2 = VectorLength2(relativepoint);
7455                         if (dist2 >= lightradius2)
7456                                 continue;
7457                         dist = sqrt(dist2) / light->radius;
7458                         intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
7459                         if (intensity <= 0.0f)
7460                                 continue;
7461                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7462                                 continue;
7463                         // scale down intensity to add to both ambient and diffuse
7464                         //intensity *= 0.5f;
7465                         VectorNormalize(relativepoint);
7466                         VectorScale(light->currentcolor, intensity, color);
7467                         VectorMA(sample    , 0.5f            , color, sample    );
7468                         VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7469                         VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7470                         VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7471                         // calculate a weighted average light direction as well
7472                         intensity *= VectorLength(color);
7473                         VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7474                 }
7475                 // FIXME: sample bouncegrid too!
7476         }
7477
7478         if (flags & LP_DYNLIGHT)
7479         {
7480                 // sample dlights
7481                 for (i = 0;i < r_refdef.scene.numlights;i++)
7482                 {
7483                         light = r_refdef.scene.lights[i];
7484                         // sample
7485                         lightradius2 = light->radius * light->radius;
7486                         VectorSubtract(light->shadoworigin, p, relativepoint);
7487                         dist2 = VectorLength2(relativepoint);
7488                         if (dist2 >= lightradius2)
7489                                 continue;
7490                         dist = sqrt(dist2) / light->radius;
7491                         intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
7492                         if (intensity <= 0.0f)
7493                                 continue;
7494                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7495                                 continue;
7496                         // scale down intensity to add to both ambient and diffuse
7497                         //intensity *= 0.5f;
7498                         VectorNormalize(relativepoint);
7499                         VectorScale(light->currentcolor, intensity, color);
7500                         VectorMA(sample    , 0.5f            , color, sample    );
7501                         VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7502                         VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7503                         VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7504                         // calculate a weighted average light direction as well
7505                         intensity *= VectorLength(color);
7506                         VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7507                 }
7508         }
7509
7510         // calculate the direction we'll use to reduce the sample to a directional light source
7511         VectorCopy(sample + 12, dir);
7512         //VectorSet(dir, sample[3] + sample[4] + sample[5], sample[6] + sample[7] + sample[8], sample[9] + sample[10] + sample[11]);
7513         VectorNormalize(dir);
7514         // extract the diffuse color along the chosen direction and scale it
7515         diffuse[0] = (dir[0]*sample[3] + dir[1]*sample[6] + dir[2]*sample[ 9] + sample[ 0]);
7516         diffuse[1] = (dir[0]*sample[4] + dir[1]*sample[7] + dir[2]*sample[10] + sample[ 1]);
7517         diffuse[2] = (dir[0]*sample[5] + dir[1]*sample[8] + dir[2]*sample[11] + sample[ 2]);
7518         // subtract some of diffuse from ambient
7519         VectorMA(sample, -0.333f, diffuse, ambient);
7520         // store the normalized lightdir
7521         VectorCopy(dir, lightdir);
7522 }