]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - r_shadow.c
Added an implementation of Lehmer random number generator with Lecuyer constant,...
[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         vec3_t bouncerandom[10];
3192         dlight_t *light;
3193         int bouncecount;
3194         int hitsupercontentsmask;
3195         int skipsupercontentsmask;
3196         int maxbounce;
3197         int shootparticles;
3198         int shotparticles;
3199         trace_t cliptrace;
3200         //trace_t cliptrace2;
3201         //trace_t cliptrace3;
3202         unsigned int lightindex;
3203         unsigned int seed = (unsigned int)(realtime * 1000.0f);
3204         randomseed_t randomseed;
3205         vec3_t shotcolor;
3206         vec3_t baseshotcolor;
3207         vec3_t surfcolor;
3208         vec3_t clipend;
3209         vec3_t clipstart;
3210         vec3_t clipdiff;
3211         vec_t radius;
3212         vec_t s;
3213         rtlight_t *rtlight;
3214
3215         Math_RandomSeed_FromInt(&randomseed, seed);
3216
3217         r_shadow_bouncegrid_state.numsplatpaths = 0;
3218         r_shadow_bouncegrid_state.splatpaths = (r_shadow_bouncegrid_splatpath_t *)R_FrameData_Alloc(sizeof(r_shadow_bouncegrid_splatpath_t) * r_shadow_bouncegrid_state.maxsplatpaths);
3219
3220         // figure out what we want to interact with
3221         if (settings.hitmodels)
3222                 hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;// | SUPERCONTENTS_LIQUIDSMASK;
3223         else
3224                 hitsupercontentsmask = SUPERCONTENTS_SOLID;// | SUPERCONTENTS_LIQUIDSMASK;
3225         skipsupercontentsmask = SUPERCONTENTS_SKY; // this allows the e1m5 sky shadow to work by ignoring the sky surfaces
3226         maxbounce = settings.maxbounce;
3227
3228         for (lightindex = 0;lightindex < range2;lightindex++)
3229         {
3230                 if (lightindex < range)
3231                 {
3232                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3233                         if (!light)
3234                                 continue;
3235                         rtlight = &light->rtlight;
3236                 }
3237                 else
3238                         rtlight = r_refdef.scene.lights[lightindex - range];
3239                 // note that this code used to keep track of residual photons and
3240                 // distribute them evenly to achieve exactly a desired photon count,
3241                 // but that caused unwanted flickering in dynamic mode
3242                 shootparticles = (int)floor(rtlight->photons * photonscaling);
3243                 // skip if we won't be shooting any photons
3244                 if (!shootparticles)
3245                         continue;
3246                 radius = rtlight->radius * settings.lightradiusscale;
3247                 s = settings.particleintensity / shootparticles;
3248                 VectorScale(rtlight->photoncolor, s, baseshotcolor);
3249                 r_refdef.stats[r_stat_bouncegrid_lights]++;
3250                 r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
3251                 switch (settings.stablerandom)
3252                 {
3253                 default:
3254                         break;
3255                 case 1:
3256                         Math_RandomSeed_FromInt(&randomseed, lightindex * 11937);
3257                         // prime the random number generator a bit
3258                         Math_crandomf(&randomseed);
3259                         break;
3260                 case 2:
3261                         seed = lightindex * 11937;
3262                         // prime the random number generator a bit
3263                         lhcheeserand(seed);
3264                         break;
3265                 }
3266                 for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
3267                 {
3268                         VectorCopy(baseshotcolor, shotcolor);
3269                         VectorCopy(rtlight->shadoworigin, clipstart);
3270                         switch (settings.stablerandom)
3271                         {
3272                         default:
3273                         case 0:
3274                                 VectorRandom(clipend);
3275                                 if (settings.bounceanglediffuse)
3276                                 {
3277                                         // we want random to be stable, so we still have to do all the random we would have done
3278                                         for (bouncecount = 0; bouncecount < maxbounce; bouncecount++)
3279                                                 VectorRandom(bouncerandom[bouncecount]);
3280                                 }
3281                                 break;
3282                         case -1:
3283                         case 1:
3284                                 VectorLehmerRandom(&randomseed, clipend);
3285                                 if (settings.bounceanglediffuse)
3286                                 {
3287                                         // we want random to be stable, so we still have to do all the random we would have done
3288                                         for (bouncecount = 0; bouncecount < maxbounce; bouncecount++)
3289                                                 VectorLehmerRandom(&randomseed, bouncerandom[bouncecount]);
3290                                 }
3291                                 break;
3292                         case -2:
3293                         case 2:
3294                                 VectorCheeseRandom(seed, clipend);
3295                                 if (settings.bounceanglediffuse)
3296                                 {
3297                                         // we want random to be stable, so we still have to do all the random we would have done
3298                                         for (bouncecount = 0; bouncecount < maxbounce; bouncecount++)
3299                                                 VectorCheeseRandom(seed, bouncerandom[bouncecount]);
3300                                 }
3301                                 break;
3302                         }
3303                         VectorMA(clipstart, radius, clipend, clipend);
3304                         for (bouncecount = 0;;bouncecount++)
3305                         {
3306                                 r_refdef.stats[r_stat_bouncegrid_traces]++;
3307                                 //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
3308                                 //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
3309                                 if (settings.staticmode || settings.stablerandom <= 0)
3310                                 {
3311                                         // static mode fires a LOT of rays but none of them are identical, so they are not cached
3312                                         // non-stable random in dynamic mode also never reuses a direction, so there's no reason to cache it
3313                                         cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true);
3314                                 }
3315                                 else
3316                                 {
3317                                         // dynamic mode fires many rays and most will match the cache from the previous frame
3318                                         cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask, skipsupercontentsmask);
3319                                 }
3320                                 if (bouncecount > 0 || settings.includedirectlighting)
3321                                 {
3322                                         vec3_t hitpos;
3323                                         VectorCopy(cliptrace.endpos, hitpos);
3324                                         R_Shadow_BounceGrid_AddSplatPath(clipstart, hitpos, shotcolor);
3325                                 }
3326                                 if (cliptrace.fraction >= 1.0f)
3327                                         break;
3328                                 r_refdef.stats[r_stat_bouncegrid_hits]++;
3329                                 if (bouncecount >= maxbounce)
3330                                         break;
3331                                 // scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
3332                                 // also clamp the resulting color to never add energy, even if the user requests extreme values
3333                                 if (cliptrace.hittexture && cliptrace.hittexture->currentskinframe)
3334                                         VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, surfcolor);
3335                                 else
3336                                         VectorSet(surfcolor, 0.5f, 0.5f, 0.5f);
3337                                 VectorScale(surfcolor, settings.particlebounceintensity, surfcolor);
3338                                 surfcolor[0] = min(surfcolor[0], 1.0f);
3339                                 surfcolor[1] = min(surfcolor[1], 1.0f);
3340                                 surfcolor[2] = min(surfcolor[2], 1.0f);
3341                                 VectorMultiply(shotcolor, surfcolor, shotcolor);
3342                                 if (VectorLength2(baseshotcolor) == 0.0f)
3343                                         break;
3344                                 r_refdef.stats[r_stat_bouncegrid_bounces]++;
3345                                 if (settings.bounceanglediffuse)
3346                                 {
3347                                         // random direction, primarily along plane normal
3348                                         s = VectorDistance(cliptrace.endpos, clipend);
3349                                         VectorMA(cliptrace.plane.normal, 0.95f, bouncerandom[bouncecount], clipend);
3350                                         VectorNormalize(clipend);
3351                                         VectorScale(clipend, s, clipend);
3352                                 }
3353                                 else
3354                                 {
3355                                         // reflect the remaining portion of the line across plane normal
3356                                         VectorSubtract(clipend, cliptrace.endpos, clipdiff);
3357                                         VectorReflect(clipdiff, 1.0, cliptrace.plane.normal, clipend);
3358                                 }
3359                                 // calculate the new line start and end
3360                                 VectorCopy(cliptrace.endpos, clipstart);
3361                                 VectorAdd(clipstart, clipend, clipend);
3362                         }
3363                 }
3364         }
3365 }
3366
3367 void R_Shadow_UpdateBounceGridTexture(void)
3368 {
3369         int flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
3370         r_shadow_bouncegrid_settings_t settings;
3371         qboolean enable = false;
3372         qboolean settingschanged;
3373         unsigned int range; // number of world lights
3374         unsigned int range1; // number of dynamic lights (or zero if disabled)
3375         unsigned int range2; // range+range1
3376         float photonscaling;
3377
3378         enable = R_Shadow_BounceGrid_CheckEnable(flag);
3379         
3380         R_Shadow_BounceGrid_GenerateSettings(&settings);
3381         
3382         // changing intensity does not require an update
3383         r_shadow_bouncegrid_state.intensity = r_shadow_bouncegrid_intensity.value;
3384
3385         settingschanged = memcmp(&r_shadow_bouncegrid_state.settings, &settings, sizeof(settings)) != 0;
3386
3387         // when settings change, we free everything as it is just simpler that way.
3388         if (settingschanged || !enable)
3389         {
3390                 // not enabled, make sure we free anything we don't need anymore.
3391                 if (r_shadow_bouncegrid_state.texture)
3392                 {
3393                         R_FreeTexture(r_shadow_bouncegrid_state.texture);
3394                         r_shadow_bouncegrid_state.texture = NULL;
3395                 }
3396                 r_shadow_bouncegrid_state.numpixels = 0;
3397                 r_shadow_bouncegrid_state.directional = false;
3398
3399                 if (!enable)
3400                         return;
3401         }
3402
3403         // if all the settings seem identical to the previous update, return
3404         if (r_shadow_bouncegrid_state.texture && (settings.staticmode || realtime < r_shadow_bouncegrid_state.lastupdatetime + r_shadow_bouncegrid_dynamic_updateinterval.value) && !settingschanged)
3405                 return;
3406
3407         // store the new settings
3408         r_shadow_bouncegrid_state.settings = settings;
3409
3410         R_Shadow_BounceGrid_UpdateSpacing();
3411
3412         // get the range of light numbers we'll be looping over:
3413         // range = static lights
3414         // range1 = dynamic lights (optional)
3415         // range2 = range + range1
3416         range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3417         range1 = settings.staticmode ? 0 : r_refdef.scene.numlights;
3418         range2 = range + range1;
3419
3420         // calculate weighting factors for distributing photons among the lights
3421         R_Shadow_BounceGrid_AssignPhotons(&settings, range, range1, range2, flag, &photonscaling);
3422
3423         // trace the photons from lights and accumulate illumination
3424         R_Shadow_BounceGrid_TracePhotons(settings, range, range1, range2, photonscaling, flag);
3425
3426         // clear the texture
3427         R_Shadow_BounceGrid_ClearPixels();
3428         
3429         // accumulate the light splatting into texture
3430         R_Shadow_BounceGrid_PerformSplats();
3431
3432         // apply a mild blur filter to the texture
3433         R_Shadow_BounceGrid_BlurPixels();
3434
3435         // convert the pixels to lower precision and upload the texture
3436         R_Shadow_BounceGrid_ConvertPixelsAndUpload();
3437 }
3438
3439 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
3440 {
3441         R_Shadow_RenderMode_Reset();
3442         GL_BlendFunc(GL_ONE, GL_ONE);
3443         GL_DepthRange(0, 1);
3444         GL_DepthTest(r_showshadowvolumes.integer < 2);
3445         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
3446         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
3447         GL_CullFace(GL_NONE);
3448         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
3449 }
3450
3451 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
3452 {
3453         R_Shadow_RenderMode_Reset();
3454         GL_BlendFunc(GL_ONE, GL_ONE);
3455         GL_DepthRange(0, 1);
3456         GL_DepthTest(r_showlighting.integer < 2);
3457         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
3458         if (!transparent)
3459                 GL_DepthFunc(GL_EQUAL);
3460         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
3461         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
3462 }
3463
3464 void R_Shadow_RenderMode_End(void)
3465 {
3466         R_Shadow_RenderMode_Reset();
3467         R_Shadow_RenderMode_ActiveLight(NULL);
3468         GL_DepthMask(true);
3469         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3470         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
3471 }
3472
3473 int bboxedges[12][2] =
3474 {
3475         // top
3476         {0, 1}, // +X
3477         {0, 2}, // +Y
3478         {1, 3}, // Y, +X
3479         {2, 3}, // X, +Y
3480         // bottom
3481         {4, 5}, // +X
3482         {4, 6}, // +Y
3483         {5, 7}, // Y, +X
3484         {6, 7}, // X, +Y
3485         // verticals
3486         {0, 4}, // +Z
3487         {1, 5}, // X, +Z
3488         {2, 6}, // Y, +Z
3489         {3, 7}, // XY, +Z
3490 };
3491
3492 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
3493 {
3494         if (!r_shadow_scissor.integer || r_shadow_usingdeferredprepass || r_trippy.integer)
3495         {
3496                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
3497                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
3498                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
3499                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
3500                 return false;
3501         }
3502         if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
3503                 return true; // invisible
3504         if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
3505         || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
3506         || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
3507         || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
3508                 r_refdef.stats[r_stat_lights_scissored]++;
3509         return false;
3510 }
3511
3512 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor)
3513 {
3514         int i;
3515         const float *vertex3f;
3516         const float *normal3f;
3517         float *color4f;
3518         float dist, dot, distintensity, shadeintensity, v[3], n[3];
3519         switch (r_shadow_rendermode)
3520         {
3521         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3522         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3523                 if (VectorLength2(diffusecolor) > 0)
3524                 {
3525                         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)
3526                         {
3527                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3528                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3529                                 if ((dot = DotProduct(n, v)) < 0)
3530                                 {
3531                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3532                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
3533                                 }
3534                                 else
3535                                         VectorCopy(ambientcolor, color4f);
3536                                 if (r_refdef.fogenabled)
3537                                 {
3538                                         float f;
3539                                         f = RSurf_FogVertex(vertex3f);
3540                                         VectorScale(color4f, f, color4f);
3541                                 }
3542                                 color4f[3] = 1;
3543                         }
3544                 }
3545                 else
3546                 {
3547                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3548                         {
3549                                 VectorCopy(ambientcolor, color4f);
3550                                 if (r_refdef.fogenabled)
3551                                 {
3552                                         float f;
3553                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3554                                         f = RSurf_FogVertex(vertex3f);
3555                                         VectorScale(color4f + 4*i, f, color4f);
3556                                 }
3557                                 color4f[3] = 1;
3558                         }
3559                 }
3560                 break;
3561         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3562                 if (VectorLength2(diffusecolor) > 0)
3563                 {
3564                         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)
3565                         {
3566                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3567                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3568                                 {
3569                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3570                                         if ((dot = DotProduct(n, v)) < 0)
3571                                         {
3572                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3573                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3574                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3575                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3576                                         }
3577                                         else
3578                                         {
3579                                                 color4f[0] = ambientcolor[0] * distintensity;
3580                                                 color4f[1] = ambientcolor[1] * distintensity;
3581                                                 color4f[2] = ambientcolor[2] * distintensity;
3582                                         }
3583                                         if (r_refdef.fogenabled)
3584                                         {
3585                                                 float f;
3586                                                 f = RSurf_FogVertex(vertex3f);
3587                                                 VectorScale(color4f, f, color4f);
3588                                         }
3589                                 }
3590                                 else
3591                                         VectorClear(color4f);
3592                                 color4f[3] = 1;
3593                         }
3594                 }
3595                 else
3596                 {
3597                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3598                         {
3599                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3600                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3601                                 {
3602                                         color4f[0] = ambientcolor[0] * distintensity;
3603                                         color4f[1] = ambientcolor[1] * distintensity;
3604                                         color4f[2] = ambientcolor[2] * distintensity;
3605                                         if (r_refdef.fogenabled)
3606                                         {
3607                                                 float f;
3608                                                 f = RSurf_FogVertex(vertex3f);
3609                                                 VectorScale(color4f, f, color4f);
3610                                         }
3611                                 }
3612                                 else
3613                                         VectorClear(color4f);
3614                                 color4f[3] = 1;
3615                         }
3616                 }
3617                 break;
3618         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3619                 if (VectorLength2(diffusecolor) > 0)
3620                 {
3621                         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)
3622                         {
3623                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3624                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3625                                 {
3626                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3627                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3628                                         if ((dot = DotProduct(n, v)) < 0)
3629                                         {
3630                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3631                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3632                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3633                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3634                                         }
3635                                         else
3636                                         {
3637                                                 color4f[0] = ambientcolor[0] * distintensity;
3638                                                 color4f[1] = ambientcolor[1] * distintensity;
3639                                                 color4f[2] = ambientcolor[2] * distintensity;
3640                                         }
3641                                         if (r_refdef.fogenabled)
3642                                         {
3643                                                 float f;
3644                                                 f = RSurf_FogVertex(vertex3f);
3645                                                 VectorScale(color4f, f, color4f);
3646                                         }
3647                                 }
3648                                 else
3649                                         VectorClear(color4f);
3650                                 color4f[3] = 1;
3651                         }
3652                 }
3653                 else
3654                 {
3655                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3656                         {
3657                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3658                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3659                                 {
3660                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3661                                         color4f[0] = ambientcolor[0] * distintensity;
3662                                         color4f[1] = ambientcolor[1] * distintensity;
3663                                         color4f[2] = ambientcolor[2] * distintensity;
3664                                         if (r_refdef.fogenabled)
3665                                         {
3666                                                 float f;
3667                                                 f = RSurf_FogVertex(vertex3f);
3668                                                 VectorScale(color4f, f, color4f);
3669                                         }
3670                                 }
3671                                 else
3672                                         VectorClear(color4f);
3673                                 color4f[3] = 1;
3674                         }
3675                 }
3676                 break;
3677         default:
3678                 break;
3679         }
3680 }
3681
3682 static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
3683 {
3684         // used to display how many times a surface is lit for level design purposes
3685         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3686         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
3687         RSurf_DrawBatch();
3688 }
3689
3690 static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
3691 {
3692         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
3693         R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
3694         RSurf_DrawBatch();
3695 }
3696
3697 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
3698 {
3699         int renders;
3700         int i;
3701         int stop;
3702         int newfirstvertex;
3703         int newlastvertex;
3704         int newnumtriangles;
3705         int *newe;
3706         const int *e;
3707         float *c;
3708         int maxtriangles = 1024;
3709         int newelements[1024*3];
3710         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
3711         for (renders = 0;renders < 4;renders++)
3712         {
3713                 stop = true;
3714                 newfirstvertex = 0;
3715                 newlastvertex = 0;
3716                 newnumtriangles = 0;
3717                 newe = newelements;
3718                 // due to low fillrate on the cards this vertex lighting path is
3719                 // designed for, we manually cull all triangles that do not
3720                 // contain a lit vertex
3721                 // this builds batches of triangles from multiple surfaces and
3722                 // renders them at once
3723                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
3724                 {
3725                         if (VectorLength2(rsurface.passcolor4f + e[0] * 4) + VectorLength2(rsurface.passcolor4f + e[1] * 4) + VectorLength2(rsurface.passcolor4f + e[2] * 4) >= 0.01)
3726                         {
3727                                 if (newnumtriangles)
3728                                 {
3729                                         newfirstvertex = min(newfirstvertex, e[0]);
3730                                         newlastvertex  = max(newlastvertex, e[0]);
3731                                 }
3732                                 else
3733                                 {
3734                                         newfirstvertex = e[0];
3735                                         newlastvertex = e[0];
3736                                 }
3737                                 newfirstvertex = min(newfirstvertex, e[1]);
3738                                 newlastvertex  = max(newlastvertex, e[1]);
3739                                 newfirstvertex = min(newfirstvertex, e[2]);
3740                                 newlastvertex  = max(newlastvertex, e[2]);
3741                                 newe[0] = e[0];
3742                                 newe[1] = e[1];
3743                                 newe[2] = e[2];
3744                                 newnumtriangles++;
3745                                 newe += 3;
3746                                 if (newnumtriangles >= maxtriangles)
3747                                 {
3748                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3749                                         newnumtriangles = 0;
3750                                         newe = newelements;
3751                                         stop = false;
3752                                 }
3753                         }
3754                 }
3755                 if (newnumtriangles >= 1)
3756                 {
3757                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3758                         stop = false;
3759                 }
3760                 // if we couldn't find any lit triangles, exit early
3761                 if (stop)
3762                         break;
3763                 // now reduce the intensity for the next overbright pass
3764                 // we have to clamp to 0 here incase the drivers have improper
3765                 // handling of negative colors
3766                 // (some old drivers even have improper handling of >1 color)
3767                 stop = true;
3768                 for (i = 0, c = rsurface.passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
3769                 {
3770                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
3771                         {
3772                                 c[0] = max(0, c[0] - 1);
3773                                 c[1] = max(0, c[1] - 1);
3774                                 c[2] = max(0, c[2] - 1);
3775                                 stop = false;
3776                         }
3777                         else
3778                                 VectorClear(c);
3779                 }
3780                 // another check...
3781                 if (stop)
3782                         break;
3783         }
3784 }
3785
3786 static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale)
3787 {
3788         // OpenGL 1.1 path (anything)
3789         float ambientcolorbase[3], diffusecolorbase[3];
3790         float ambientcolorpants[3], diffusecolorpants[3];
3791         float ambientcolorshirt[3], diffusecolorshirt[3];
3792         const float *surfacecolor = rsurface.texture->dlightcolor;
3793         const float *surfacepants = rsurface.colormap_pantscolor;
3794         const float *surfaceshirt = rsurface.colormap_shirtcolor;
3795         rtexture_t *basetexture = rsurface.texture->basetexture;
3796         rtexture_t *pantstexture = rsurface.texture->pantstexture;
3797         rtexture_t *shirttexture = rsurface.texture->shirttexture;
3798         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
3799         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
3800         ambientscale *= 2 * r_refdef.view.colorscale;
3801         diffusescale *= 2 * r_refdef.view.colorscale;
3802         ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
3803         diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
3804         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
3805         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
3806         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
3807         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
3808         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3809         rsurface.passcolor4f = (float *)R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4]));
3810         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3811         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
3812         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
3813         R_Mesh_TexBind(0, basetexture);
3814         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
3815         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
3816         switch(r_shadow_rendermode)
3817         {
3818         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3819                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
3820                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
3821                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
3822                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3823                 break;
3824         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3825                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
3826                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
3827                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
3828                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3829                 // fall through
3830         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3831                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
3832                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
3833                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
3834                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3835                 break;
3836         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3837                 break;
3838         default:
3839                 break;
3840         }
3841         //R_Mesh_TexBind(0, basetexture);
3842         R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase);
3843         if (dopants)
3844         {
3845                 R_Mesh_TexBind(0, pantstexture);
3846                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants);
3847         }
3848         if (doshirt)
3849         {
3850                 R_Mesh_TexBind(0, shirttexture);
3851                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt);
3852         }
3853 }
3854
3855 extern cvar_t gl_lightmaps;
3856 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
3857 {
3858         float ambientscale, diffusescale, specularscale;
3859         qboolean negated;
3860         float lightcolor[3];
3861         VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
3862         ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient;
3863         diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient);
3864         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
3865         if (!r_shadow_usenormalmap.integer)
3866         {
3867                 ambientscale += 1.0f * diffusescale;
3868                 diffusescale = 0;
3869                 specularscale = 0;
3870         }
3871         if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
3872                 return;
3873         negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
3874         if(negated)
3875         {
3876                 VectorNegate(lightcolor, lightcolor);
3877                 GL_BlendEquationSubtract(true);
3878         }
3879         RSurf_SetupDepthAndCulling();
3880         switch (r_shadow_rendermode)
3881         {
3882         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
3883                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
3884                 R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
3885                 break;
3886         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
3887                 R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale);
3888                 break;
3889         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3890         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3891         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3892         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3893                 R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale);
3894                 break;
3895         default:
3896                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
3897                 break;
3898         }
3899         if(negated)
3900                 GL_BlendEquationSubtract(false);
3901 }
3902
3903 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)
3904 {
3905         matrix4x4_t tempmatrix = *matrix;
3906         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
3907
3908         // if this light has been compiled before, free the associated data
3909         R_RTLight_Uncompile(rtlight);
3910
3911         // clear it completely to avoid any lingering data
3912         memset(rtlight, 0, sizeof(*rtlight));
3913
3914         // copy the properties
3915         rtlight->matrix_lighttoworld = tempmatrix;
3916         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
3917         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
3918         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
3919         VectorCopy(color, rtlight->color);
3920         rtlight->cubemapname[0] = 0;
3921         if (cubemapname && cubemapname[0])
3922                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
3923         rtlight->shadow = shadow;
3924         rtlight->corona = corona;
3925         rtlight->style = style;
3926         rtlight->isstatic = isstatic;
3927         rtlight->coronasizescale = coronasizescale;
3928         rtlight->ambientscale = ambientscale;
3929         rtlight->diffusescale = diffusescale;
3930         rtlight->specularscale = specularscale;
3931         rtlight->flags = flags;
3932
3933         // compute derived data
3934         //rtlight->cullradius = rtlight->radius;
3935         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
3936         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3937         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3938         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3939         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3940         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3941         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3942 }
3943
3944 // compiles rtlight geometry
3945 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
3946 void R_RTLight_Compile(rtlight_t *rtlight)
3947 {
3948         int i;
3949         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
3950         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
3951         entity_render_t *ent = r_refdef.scene.worldentity;
3952         dp_model_t *model = r_refdef.scene.worldmodel;
3953         unsigned char *data;
3954         shadowmesh_t *mesh;
3955
3956         // compile the light
3957         rtlight->compiled = true;
3958         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
3959         rtlight->static_numleafs = 0;
3960         rtlight->static_numleafpvsbytes = 0;
3961         rtlight->static_leaflist = NULL;
3962         rtlight->static_leafpvs = NULL;
3963         rtlight->static_numsurfaces = 0;
3964         rtlight->static_surfacelist = NULL;
3965         rtlight->static_shadowmap_receivers = 0x3F;
3966         rtlight->static_shadowmap_casters = 0x3F;
3967         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3968         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3969         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3970         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3971         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3972         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3973
3974         if (model && model->GetLightInfo)
3975         {
3976                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
3977                 r_shadow_compilingrtlight = rtlight;
3978                 R_FrameData_SetMark();
3979                 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);
3980                 R_FrameData_ReturnToMark();
3981                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
3982                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
3983                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
3984                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
3985                 rtlight->static_numsurfaces = numsurfaces;
3986                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
3987                 rtlight->static_numleafs = numleafs;
3988                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
3989                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
3990                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
3991                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
3992                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
3993                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
3994                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
3995                 if (rtlight->static_numsurfaces)
3996                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
3997                 if (rtlight->static_numleafs)
3998                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3999                 if (rtlight->static_numleafpvsbytes)
4000                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
4001                 if (rtlight->static_numshadowtrispvsbytes)
4002                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
4003                 if (rtlight->static_numlighttrispvsbytes)
4004                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
4005                 R_FrameData_SetMark();
4006                 switch (rtlight->shadowmode)
4007                 {
4008                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
4009                         if (model->CompileShadowMap && rtlight->shadow)
4010                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
4011                         break;
4012                 default:
4013                         if (model->CompileShadowVolume && rtlight->shadow)
4014                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
4015                         break;
4016                 }
4017                 R_FrameData_ReturnToMark();
4018                 // now we're done compiling the rtlight
4019                 r_shadow_compilingrtlight = NULL;
4020         }
4021
4022
4023         // use smallest available cullradius - box radius or light radius
4024         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
4025         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
4026
4027         shadowzpasstris = 0;
4028         if (rtlight->static_meshchain_shadow_zpass)
4029                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
4030                         shadowzpasstris += mesh->numtriangles;
4031
4032         shadowzfailtris = 0;
4033         if (rtlight->static_meshchain_shadow_zfail)
4034                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
4035                         shadowzfailtris += mesh->numtriangles;
4036
4037         lighttris = 0;
4038         if (rtlight->static_numlighttrispvsbytes)
4039                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
4040                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
4041                                 lighttris++;
4042
4043         shadowtris = 0;
4044         if (rtlight->static_numshadowtrispvsbytes)
4045                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
4046                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
4047                                 shadowtris++;
4048
4049         if (developer_extra.integer)
4050                 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);
4051 }
4052
4053 void R_RTLight_Uncompile(rtlight_t *rtlight)
4054 {
4055         if (rtlight->compiled)
4056         {
4057                 if (rtlight->static_meshchain_shadow_zpass)
4058                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
4059                 rtlight->static_meshchain_shadow_zpass = NULL;
4060                 if (rtlight->static_meshchain_shadow_zfail)
4061                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
4062                 rtlight->static_meshchain_shadow_zfail = NULL;
4063                 if (rtlight->static_meshchain_shadow_shadowmap)
4064                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
4065                 rtlight->static_meshchain_shadow_shadowmap = NULL;
4066                 // these allocations are grouped
4067                 if (rtlight->static_surfacelist)
4068                         Mem_Free(rtlight->static_surfacelist);
4069                 rtlight->static_numleafs = 0;
4070                 rtlight->static_numleafpvsbytes = 0;
4071                 rtlight->static_leaflist = NULL;
4072                 rtlight->static_leafpvs = NULL;
4073                 rtlight->static_numsurfaces = 0;
4074                 rtlight->static_surfacelist = NULL;
4075                 rtlight->static_numshadowtrispvsbytes = 0;
4076                 rtlight->static_shadowtrispvs = NULL;
4077                 rtlight->static_numlighttrispvsbytes = 0;
4078                 rtlight->static_lighttrispvs = NULL;
4079                 rtlight->compiled = false;
4080         }
4081 }
4082
4083 void R_Shadow_UncompileWorldLights(void)
4084 {
4085         size_t lightindex;
4086         dlight_t *light;
4087         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4088         for (lightindex = 0;lightindex < range;lightindex++)
4089         {
4090                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4091                 if (!light)
4092                         continue;
4093                 R_RTLight_Uncompile(&light->rtlight);
4094         }
4095 }
4096
4097 static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
4098 {
4099         int i, j;
4100         mplane_t plane;
4101         // reset the count of frustum planes
4102         // see rtlight->cached_frustumplanes definition for how much this array
4103         // can hold
4104         rtlight->cached_numfrustumplanes = 0;
4105
4106         if (r_trippy.integer)
4107                 return;
4108
4109         // haven't implemented a culling path for ortho rendering
4110         if (!r_refdef.view.useperspective)
4111         {
4112                 // check if the light is on screen and copy the 4 planes if it is
4113                 for (i = 0;i < 4;i++)
4114                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
4115                                 break;
4116                 if (i == 4)
4117                         for (i = 0;i < 4;i++)
4118                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
4119                 return;
4120         }
4121
4122 #if 1
4123         // generate a deformed frustum that includes the light origin, this is
4124         // used to cull shadow casting surfaces that can not possibly cast a
4125         // shadow onto the visible light-receiving surfaces, which can be a
4126         // performance gain
4127         //
4128         // if the light origin is onscreen the result will be 4 planes exactly
4129         // if the light origin is offscreen on only one axis the result will
4130         // be exactly 5 planes (split-side case)
4131         // if the light origin is offscreen on two axes the result will be
4132         // exactly 4 planes (stretched corner case)
4133         for (i = 0;i < 4;i++)
4134         {
4135                 // quickly reject standard frustum planes that put the light
4136                 // origin outside the frustum
4137                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
4138                         continue;
4139                 // copy the plane
4140                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
4141         }
4142         // if all the standard frustum planes were accepted, the light is onscreen
4143         // otherwise we need to generate some more planes below...
4144         if (rtlight->cached_numfrustumplanes < 4)
4145         {
4146                 // at least one of the stock frustum planes failed, so we need to
4147                 // create one or two custom planes to enclose the light origin
4148                 for (i = 0;i < 4;i++)
4149                 {
4150                         // create a plane using the view origin and light origin, and a
4151                         // single point from the frustum corner set
4152                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
4153                         VectorNormalize(plane.normal);
4154                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
4155                         // see if this plane is backwards and flip it if so
4156                         for (j = 0;j < 4;j++)
4157                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
4158                                         break;
4159                         if (j < 4)
4160                         {
4161                                 VectorNegate(plane.normal, plane.normal);
4162                                 plane.dist *= -1;
4163                                 // flipped plane, test again to see if it is now valid
4164                                 for (j = 0;j < 4;j++)
4165                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
4166                                                 break;
4167                                 // if the plane is still not valid, then it is dividing the
4168                                 // frustum and has to be rejected
4169                                 if (j < 4)
4170                                         continue;
4171                         }
4172                         // we have created a valid plane, compute extra info
4173                         PlaneClassify(&plane);
4174                         // copy the plane
4175                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4176 #if 1
4177                         // if we've found 5 frustum planes then we have constructed a
4178                         // proper split-side case and do not need to keep searching for
4179                         // planes to enclose the light origin
4180                         if (rtlight->cached_numfrustumplanes == 5)
4181                                 break;
4182 #endif
4183                 }
4184         }
4185 #endif
4186
4187 #if 0
4188         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
4189         {
4190                 plane = rtlight->cached_frustumplanes[i];
4191                 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));
4192         }
4193 #endif
4194
4195 #if 0
4196         // now add the light-space box planes if the light box is rotated, as any
4197         // caster outside the oriented light box is irrelevant (even if it passed
4198         // the worldspace light box, which is axial)
4199         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
4200         {
4201                 for (i = 0;i < 6;i++)
4202                 {
4203                         vec3_t v;
4204                         VectorClear(v);
4205                         v[i >> 1] = (i & 1) ? -1 : 1;
4206                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
4207                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
4208                         plane.dist = VectorNormalizeLength(plane.normal);
4209                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
4210                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4211                 }
4212         }
4213 #endif
4214
4215 #if 0
4216         // add the world-space reduced box planes
4217         for (i = 0;i < 6;i++)
4218         {
4219                 VectorClear(plane.normal);
4220                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
4221                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
4222                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
4223         }
4224 #endif
4225
4226 #if 0
4227         {
4228         int j, oldnum;
4229         vec3_t points[8];
4230         vec_t bestdist;
4231         // reduce all plane distances to tightly fit the rtlight cull box, which
4232         // is in worldspace
4233         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
4234         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
4235         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
4236         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
4237         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
4238         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
4239         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
4240         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
4241         oldnum = rtlight->cached_numfrustumplanes;
4242         rtlight->cached_numfrustumplanes = 0;
4243         for (j = 0;j < oldnum;j++)
4244         {
4245                 // find the nearest point on the box to this plane
4246                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
4247                 for (i = 1;i < 8;i++)
4248                 {
4249                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
4250                         if (bestdist > dist)
4251                                 bestdist = dist;
4252                 }
4253                 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);
4254                 // if the nearest point is near or behind the plane, we want this
4255                 // plane, otherwise the plane is useless as it won't cull anything
4256                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
4257                 {
4258                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
4259                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
4260                 }
4261         }
4262         }
4263 #endif
4264 }
4265
4266 static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
4267 {
4268         shadowmesh_t *mesh;
4269
4270         RSurf_ActiveWorldEntity();
4271
4272         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
4273         {
4274                 CHECKGLERROR
4275                 GL_CullFace(GL_NONE);
4276                 mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
4277                 for (;mesh;mesh = mesh->next)
4278                 {
4279                         if (!mesh->sidetotals[r_shadow_shadowmapside])
4280                                 continue;
4281                         r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside];
4282                         R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
4283                         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);
4284                 }
4285                 CHECKGLERROR
4286         }
4287         else if (r_refdef.scene.worldentity->model)
4288                 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);
4289
4290         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4291 }
4292
4293 static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
4294 {
4295         qboolean zpass = false;
4296         shadowmesh_t *mesh;
4297         int t, tend;
4298         int surfacelistindex;
4299         msurface_t *surface;
4300
4301         // if triangle neighbors are disabled, shadowvolumes are disabled
4302         if (r_refdef.scene.worldmodel->brush.shadowmesh ? !r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i : !r_refdef.scene.worldmodel->surfmesh.data_neighbor3i)
4303                 return;
4304
4305         RSurf_ActiveWorldEntity();
4306
4307         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
4308         {
4309                 CHECKGLERROR
4310                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
4311                 {
4312                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
4313                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
4314                 }
4315                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
4316                 for (;mesh;mesh = mesh->next)
4317                 {
4318                         r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->numtriangles;
4319                         R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
4320                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
4321                         {
4322                                 // increment stencil if frontface is infront of depthbuffer
4323                                 GL_CullFace(r_refdef.view.cullface_back);
4324                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
4325                                 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);
4326                                 // decrement stencil if backface is infront of depthbuffer
4327                                 GL_CullFace(r_refdef.view.cullface_front);
4328                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
4329                         }
4330                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
4331                         {
4332                                 // decrement stencil if backface is behind depthbuffer
4333                                 GL_CullFace(r_refdef.view.cullface_front);
4334                                 R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
4335                                 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);
4336                                 // increment stencil if frontface is behind depthbuffer
4337                                 GL_CullFace(r_refdef.view.cullface_back);
4338                                 R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
4339                         }
4340                         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);
4341                 }
4342                 CHECKGLERROR
4343         }
4344         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
4345         {
4346                 // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
4347                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
4348                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
4349                 {
4350                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
4351                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
4352                                 if (CHECKPVSBIT(trispvs, t))
4353                                         shadowmarklist[numshadowmark++] = t;
4354                 }
4355                 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);
4356         }
4357         else if (numsurfaces)
4358         {
4359                 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);
4360         }
4361
4362         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4363 }
4364
4365 static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
4366 {
4367         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
4368         vec_t relativeshadowradius;
4369         RSurf_ActiveModelEntity(ent, false, false, false);
4370         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
4371         // we need to re-init the shader for each entity because the matrix changed
4372         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
4373         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
4374         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
4375         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
4376         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
4377         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
4378         relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
4379         switch (r_shadow_rendermode)
4380         {
4381         case R_SHADOW_RENDERMODE_SHADOWMAP2D:
4382                 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
4383                 break;
4384         default:
4385                 ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
4386                 break;
4387         }
4388         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4389 }
4390
4391 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
4392 {
4393         // set up properties for rendering light onto this entity
4394         RSurf_ActiveModelEntity(ent, true, true, false);
4395         Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
4396         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
4397         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
4398         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
4399 }
4400
4401 static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
4402 {
4403         if (!r_refdef.scene.worldmodel->DrawLight)
4404                 return;
4405
4406         // set up properties for rendering light onto this entity
4407         RSurf_ActiveWorldEntity();
4408         rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
4409         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
4410         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
4411         VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
4412
4413         r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
4414
4415         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4416 }
4417
4418 static void R_Shadow_DrawEntityLight(entity_render_t *ent)
4419 {
4420         dp_model_t *model = ent->model;
4421         if (!model->DrawLight)
4422                 return;
4423
4424         R_Shadow_SetupEntityLight(ent);
4425
4426         model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
4427
4428         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4429 }
4430
4431 static void R_Shadow_PrepareLight(rtlight_t *rtlight)
4432 {
4433         int i;
4434         float f;
4435         int numleafs, numsurfaces;
4436         int *leaflist, *surfacelist;
4437         unsigned char *leafpvs;
4438         unsigned char *shadowtrispvs;
4439         unsigned char *lighttrispvs;
4440         //unsigned char *surfacesides;
4441         int numlightentities;
4442         int numlightentities_noselfshadow;
4443         int numshadowentities;
4444         int numshadowentities_noselfshadow;
4445         // FIXME: bounds check lightentities and shadowentities, etc.
4446         static entity_render_t *lightentities[MAX_EDICTS];
4447         static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
4448         static entity_render_t *shadowentities[MAX_EDICTS];
4449         static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
4450         qboolean nolight;
4451         qboolean castshadows;
4452
4453         rtlight->draw = false;
4454         rtlight->cached_numlightentities = 0;
4455         rtlight->cached_numlightentities_noselfshadow = 0;
4456         rtlight->cached_numshadowentities = 0;
4457         rtlight->cached_numshadowentities_noselfshadow = 0;
4458         rtlight->cached_numsurfaces = 0;
4459         rtlight->cached_lightentities = NULL;
4460         rtlight->cached_lightentities_noselfshadow = NULL;
4461         rtlight->cached_shadowentities = NULL;
4462         rtlight->cached_shadowentities_noselfshadow = NULL;
4463         rtlight->cached_shadowtrispvs = NULL;
4464         rtlight->cached_lighttrispvs = NULL;
4465         rtlight->cached_surfacelist = NULL;
4466         rtlight->shadowmapsidesize = 0;
4467
4468         // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
4469         // skip lights that are basically invisible (color 0 0 0)
4470         nolight = VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f);
4471
4472         // loading is done before visibility checks because loading should happen
4473         // all at once at the start of a level, not when it stalls gameplay.
4474         // (especially important to benchmarks)
4475         // compile light
4476         if (rtlight->isstatic && !nolight && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
4477         {
4478                 if (rtlight->compiled)
4479                         R_RTLight_Uncompile(rtlight);
4480                 R_RTLight_Compile(rtlight);
4481         }
4482
4483         // load cubemap
4484         rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
4485
4486         // look up the light style value at this time
4487         f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
4488         VectorScale(rtlight->color, f, rtlight->currentcolor);
4489         /*
4490         if (rtlight->selected)
4491         {
4492                 f = 2 + sin(realtime * M_PI * 4.0);
4493                 VectorScale(rtlight->currentcolor, f, rtlight->currentcolor);
4494         }
4495         */
4496
4497         // if lightstyle is currently off, don't draw the light
4498         if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
4499                 return;
4500
4501         // skip processing on corona-only lights
4502         if (nolight)
4503                 return;
4504
4505         // if the light box is offscreen, skip it
4506         if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
4507                 return;
4508
4509         VectorCopy(rtlight->cullmins, rtlight->cached_cullmins);
4510         VectorCopy(rtlight->cullmaxs, rtlight->cached_cullmaxs);
4511
4512         R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
4513
4514         // 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
4515         if (r_shadow_bouncegrid.integer == 2 && (rtlight->isstatic || !r_shadow_bouncegrid_static.integer))
4516                 return;
4517
4518         if (rtlight->compiled && r_shadow_realtime_world_compile.integer)
4519         {
4520                 // compiled light, world available and can receive realtime lighting
4521                 // retrieve leaf information
4522                 numleafs = rtlight->static_numleafs;
4523                 leaflist = rtlight->static_leaflist;
4524                 leafpvs = rtlight->static_leafpvs;
4525                 numsurfaces = rtlight->static_numsurfaces;
4526                 surfacelist = rtlight->static_surfacelist;
4527                 //surfacesides = NULL;
4528                 shadowtrispvs = rtlight->static_shadowtrispvs;
4529                 lighttrispvs = rtlight->static_lighttrispvs;
4530         }
4531         else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->GetLightInfo)
4532         {
4533                 // dynamic light, world available and can receive realtime lighting
4534                 // calculate lit surfaces and leafs
4535                 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);
4536                 R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
4537                 leaflist = r_shadow_buffer_leaflist;
4538                 leafpvs = r_shadow_buffer_leafpvs;
4539                 surfacelist = r_shadow_buffer_surfacelist;
4540                 //surfacesides = r_shadow_buffer_surfacesides;
4541                 shadowtrispvs = r_shadow_buffer_shadowtrispvs;
4542                 lighttrispvs = r_shadow_buffer_lighttrispvs;
4543                 // if the reduced leaf bounds are offscreen, skip it
4544                 if (R_CullBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4545                         return;
4546         }
4547         else
4548         {
4549                 // no world
4550                 numleafs = 0;
4551                 leaflist = NULL;
4552                 leafpvs = NULL;
4553                 numsurfaces = 0;
4554                 surfacelist = NULL;
4555                 //surfacesides = NULL;
4556                 shadowtrispvs = NULL;
4557                 lighttrispvs = NULL;
4558         }
4559         // check if light is illuminating any visible leafs
4560         if (numleafs)
4561         {
4562                 for (i = 0; i < numleafs; i++)
4563                         if (r_refdef.viewcache.world_leafvisible[leaflist[i]])
4564                                 break;
4565                 if (i == numleafs)
4566                         return;
4567         }
4568
4569         // make a list of lit entities and shadow casting entities
4570         numlightentities = 0;
4571         numlightentities_noselfshadow = 0;
4572         numshadowentities = 0;
4573         numshadowentities_noselfshadow = 0;
4574
4575         // add dynamic entities that are lit by the light
4576         for (i = 0; i < r_refdef.scene.numentities; i++)
4577         {
4578                 dp_model_t *model;
4579                 entity_render_t *ent = r_refdef.scene.entities[i];
4580                 vec3_t org;
4581                 if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4582                         continue;
4583                 // skip the object entirely if it is not within the valid
4584                 // shadow-casting region (which includes the lit region)
4585                 if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
4586                         continue;
4587                 if (!(model = ent->model))
4588                         continue;
4589                 if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
4590                 {
4591                         // this entity wants to receive light, is visible, and is
4592                         // inside the light box
4593                         // TODO: check if the surfaces in the model can receive light
4594                         // so now check if it's in a leaf seen by the light
4595                         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))
4596                                 continue;
4597                         if (ent->flags & RENDER_NOSELFSHADOW)
4598                                 lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
4599                         else
4600                                 lightentities[numlightentities++] = ent;
4601                         // since it is lit, it probably also casts a shadow...
4602                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
4603                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4604                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
4605                         {
4606                                 // note: exterior models without the RENDER_NOSELFSHADOW
4607                                 // flag still create a RENDER_NOSELFSHADOW shadow but
4608                                 // are lit normally, this means that they are
4609                                 // self-shadowing but do not shadow other
4610                                 // RENDER_NOSELFSHADOW entities such as the gun
4611                                 // (very weird, but keeps the player shadow off the gun)
4612                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
4613                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
4614                                 else
4615                                         shadowentities[numshadowentities++] = ent;
4616                         }
4617                 }
4618                 else if (ent->flags & RENDER_SHADOW)
4619                 {
4620                         // this entity is not receiving light, but may still need to
4621                         // cast a shadow...
4622                         // TODO: check if the surfaces in the model can cast shadow
4623                         // now check if it is in a leaf seen by the light
4624                         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))
4625                                 continue;
4626                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
4627                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4628                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
4629                         {
4630                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
4631                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
4632                                 else
4633                                         shadowentities[numshadowentities++] = ent;
4634                         }
4635                 }
4636         }
4637
4638         // return if there's nothing at all to light
4639         if (numsurfaces + numlightentities + numlightentities_noselfshadow == 0)
4640                 return;
4641
4642         // count this light in the r_speeds
4643         r_refdef.stats[r_stat_lights]++;
4644
4645         // flag it as worth drawing later
4646         rtlight->draw = true;
4647
4648         // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one
4649         castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
4650         if (!castshadows)
4651                 numshadowentities = numshadowentities_noselfshadow = 0;
4652         rtlight->castshadows = castshadows;
4653
4654         // cache all the animated entities that cast a shadow but are not visible
4655         for (i = 0; i < numshadowentities; i++)
4656                 R_AnimCache_GetEntity(shadowentities[i], false, false);
4657         for (i = 0; i < numshadowentities_noselfshadow; i++)
4658                 R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
4659
4660         // 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)
4661         if (numshadowentities_noselfshadow > 0 && (numlightentities_noselfshadow == 0 || r_shadow_usingdeferredprepass))
4662         {
4663                 for (i = 0; i < numshadowentities_noselfshadow; i++)
4664                         shadowentities[numshadowentities++] = shadowentities_noselfshadow[i];
4665                 numshadowentities_noselfshadow = 0;
4666         }
4667
4668         // we can convert noselfshadow to regular if there are no casters of that type
4669         if (numlightentities_noselfshadow > 0 && numshadowentities_noselfshadow == 0)
4670         {
4671                 for (i = 0; i < numlightentities_noselfshadow; i++)
4672                         lightentities[numlightentities++] = lightentities_noselfshadow[i];
4673                 numlightentities_noselfshadow = 0;
4674         }
4675
4676         // allocate some temporary memory for rendering this light later in the frame
4677         // reusable buffers need to be copied, static data can be used as-is
4678         rtlight->cached_numlightentities               = numlightentities;
4679         rtlight->cached_numlightentities_noselfshadow  = numlightentities_noselfshadow;
4680         rtlight->cached_numshadowentities              = numshadowentities;
4681         rtlight->cached_numshadowentities_noselfshadow = numshadowentities_noselfshadow;
4682         rtlight->cached_numsurfaces                    = numsurfaces;
4683         rtlight->cached_lightentities                  = (entity_render_t**)R_FrameData_Store(numlightentities*sizeof(entity_render_t*), (void*)lightentities);
4684         rtlight->cached_lightentities_noselfshadow     = (entity_render_t**)R_FrameData_Store(numlightentities_noselfshadow*sizeof(entity_render_t*), (void*)lightentities_noselfshadow);
4685         rtlight->cached_shadowentities                 = (entity_render_t**)R_FrameData_Store(numshadowentities*sizeof(entity_render_t*), (void*)shadowentities);
4686         rtlight->cached_shadowentities_noselfshadow    = (entity_render_t**)R_FrameData_Store(numshadowentities_noselfshadow*sizeof(entity_render_t *), (void*)shadowentities_noselfshadow);
4687         if (shadowtrispvs == r_shadow_buffer_shadowtrispvs)
4688         {
4689                 int numshadowtrispvsbytes = (((r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles) + 7) >> 3);
4690                 int numlighttrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
4691                 rtlight->cached_shadowtrispvs                  =   (unsigned char *)R_FrameData_Store(numshadowtrispvsbytes, shadowtrispvs);
4692                 rtlight->cached_lighttrispvs                   =   (unsigned char *)R_FrameData_Store(numlighttrispvsbytes, lighttrispvs);
4693                 rtlight->cached_surfacelist                    =              (int*)R_FrameData_Store(numsurfaces*sizeof(int), (void*)surfacelist);
4694         }
4695         else
4696         {
4697                 // compiled light data
4698                 rtlight->cached_shadowtrispvs = shadowtrispvs;
4699                 rtlight->cached_lighttrispvs = lighttrispvs;
4700                 rtlight->cached_surfacelist = surfacelist;
4701         }
4702
4703         if (R_Shadow_ShadowMappingEnabled())
4704         {
4705                 // figure out the shadowmapping parameters for this light
4706                 vec3_t nearestpoint;
4707                 vec_t distance;
4708                 int lodlinear;
4709                 nearestpoint[0] = bound(rtlight->cullmins[0], r_refdef.view.origin[0], rtlight->cullmaxs[0]);
4710                 nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
4711                 nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
4712                 distance = VectorDistance(nearestpoint, r_refdef.view.origin);
4713                 lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance / rtlight->radius));
4714                 //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
4715                 lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
4716                 rtlight->shadowmapsidesize = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
4717                 // shadowmapatlas* variables will be set by R_Shadow_PrepareLights()
4718         }
4719 }
4720
4721 static void R_Shadow_DrawLightShadowMaps(rtlight_t *rtlight)
4722 {
4723         int i;
4724         int numsurfaces;
4725         unsigned char *shadowtrispvs, *lighttrispvs, *surfacesides;
4726         int numlightentities;
4727         int numlightentities_noselfshadow;
4728         int numshadowentities;
4729         int numshadowentities_noselfshadow;
4730         entity_render_t **lightentities;
4731         entity_render_t **lightentities_noselfshadow;
4732         entity_render_t **shadowentities;
4733         entity_render_t **shadowentities_noselfshadow;
4734         int *surfacelist;
4735         static unsigned char entitysides[MAX_EDICTS];
4736         static unsigned char entitysides_noselfshadow[MAX_EDICTS];
4737         float borderbias;
4738         int side;
4739         int size;
4740         int castermask;
4741         int receivermask;
4742         matrix4x4_t radiustolight;
4743
4744         // check if we cached this light this frame (meaning it is worth drawing)
4745         if (!rtlight->draw || !rtlight->castshadows)
4746                 return;
4747
4748         // if PrepareLights could not find any space for this shadowmap, we may as well mark it as not casting shadows...
4749         if (rtlight->shadowmapatlassidesize == 0)
4750         {
4751                 rtlight->castshadows = false;
4752                 return;
4753         }
4754
4755         // set up a scissor rectangle for this light
4756         if (R_Shadow_ScissorForBBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4757                 return;
4758
4759         // don't let sound skip if going slow
4760         if (r_refdef.scene.extraupdate)
4761                 S_ExtraUpdate();
4762
4763         numlightentities = rtlight->cached_numlightentities;
4764         numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
4765         numshadowentities = rtlight->cached_numshadowentities;
4766         numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
4767         numsurfaces = rtlight->cached_numsurfaces;
4768         lightentities = rtlight->cached_lightentities;
4769         lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
4770         shadowentities = rtlight->cached_shadowentities;
4771         shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
4772         shadowtrispvs = rtlight->cached_shadowtrispvs;
4773         lighttrispvs = rtlight->cached_lighttrispvs;
4774         surfacelist = rtlight->cached_surfacelist;
4775
4776         // make this the active rtlight for rendering purposes
4777         R_Shadow_RenderMode_ActiveLight(rtlight);
4778
4779         radiustolight = rtlight->matrix_worldtolight;
4780         Matrix4x4_Abs(&radiustolight);
4781
4782         size = rtlight->shadowmapatlassidesize;
4783         borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
4784
4785         surfacesides = NULL;
4786         castermask = 0;
4787         receivermask = 0;
4788         if (numsurfaces)
4789         {
4790                 if (rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
4791                 {
4792                         castermask = rtlight->static_shadowmap_casters;
4793                         receivermask = rtlight->static_shadowmap_receivers;
4794                 }
4795                 else
4796                 {
4797                         surfacesides = r_shadow_buffer_surfacesides;
4798                         for (i = 0; i < numsurfaces; i++)
4799                         {
4800                                 msurface_t *surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[i];
4801                                 surfacesides[i] = R_Shadow_CalcBBoxSideMask(surface->mins, surface->maxs, &rtlight->matrix_worldtolight, &radiustolight, borderbias);
4802                                 castermask |= surfacesides[i];
4803                                 receivermask |= surfacesides[i];
4804                         }
4805                 }
4806         }
4807
4808         for (i = 0; i < numlightentities && receivermask < 0x3F; i++)
4809                 receivermask |= R_Shadow_CalcEntitySideMask(lightentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
4810         for (i = 0; i < numlightentities_noselfshadow && receivermask < 0x3F; i++)
4811                 receivermask |= R_Shadow_CalcEntitySideMask(lightentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
4812
4813         receivermask &= R_Shadow_CullFrustumSides(rtlight, size, r_shadow_shadowmapborder);
4814
4815         if (receivermask)
4816         {
4817                 for (i = 0; i < numshadowentities; i++)
4818                         castermask |= (entitysides[i] = R_Shadow_CalcEntitySideMask(shadowentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
4819                 for (i = 0; i < numshadowentities_noselfshadow; i++)
4820                         castermask |= (entitysides_noselfshadow[i] = R_Shadow_CalcEntitySideMask(shadowentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
4821         }
4822
4823         // there is no need to render shadows for sides that have no receivers...
4824         castermask &= receivermask;
4825
4826         //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
4827
4828         // render shadow casters into shadowmaps for this light
4829         for (side = 0; side < 6; side++)
4830         {
4831                 int bit = 1 << side;
4832                 if (castermask & bit)
4833                 {
4834                         R_Shadow_RenderMode_ShadowMap(side, size, rtlight->shadowmapatlasposition[0], rtlight->shadowmapatlasposition[1]);
4835                         if (numsurfaces)
4836                                 R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
4837                         for (i = 0; i < numshadowentities; i++)
4838                                 if (entitysides[i] & bit)
4839                                         R_Shadow_DrawEntityShadow(shadowentities[i]);
4840                         for (i = 0; i < numshadowentities_noselfshadow; i++)
4841                                 if (entitysides_noselfshadow[i] & bit)
4842                                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
4843                 }
4844         }
4845         // additionally if there are any noselfshadow casters we have to render a second set of shadowmaps without those :(
4846         if (numshadowentities_noselfshadow)
4847         {
4848                 for (side = 0; side < 6; side++)
4849                 {
4850                         int bit = 1 << side;
4851                         if (castermask & bit)
4852                         {
4853                                 R_Shadow_RenderMode_ShadowMap(side, size, rtlight->shadowmapatlasposition[0] + size * 2, rtlight->shadowmapatlasposition[1]);
4854                                 if (numsurfaces)
4855                                         R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
4856                                 for (i = 0; i < numshadowentities; i++)
4857                                         if (entitysides[i] & bit)
4858                                                 R_Shadow_DrawEntityShadow(shadowentities[i]);
4859                         }
4860                 }
4861         }
4862 }
4863
4864 static void R_Shadow_DrawLight(rtlight_t *rtlight)
4865 {
4866         int i;
4867         int numsurfaces;
4868         unsigned char *shadowtrispvs, *lighttrispvs;
4869         int numlightentities;
4870         int numlightentities_noselfshadow;
4871         int numshadowentities;
4872         int numshadowentities_noselfshadow;
4873         entity_render_t **lightentities;
4874         entity_render_t **lightentities_noselfshadow;
4875         entity_render_t **shadowentities;
4876         entity_render_t **shadowentities_noselfshadow;
4877         int *surfacelist;
4878         qboolean castshadows;
4879
4880         // check if we cached this light this frame (meaning it is worth drawing)
4881         if (!rtlight->draw)
4882                 return;
4883
4884         // set up a scissor rectangle for this light
4885         if (R_Shadow_ScissorForBBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
4886                 return;
4887
4888         // don't let sound skip if going slow
4889         if (r_refdef.scene.extraupdate)
4890                 S_ExtraUpdate();
4891
4892         numlightentities = rtlight->cached_numlightentities;
4893         numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
4894         numshadowentities = rtlight->cached_numshadowentities;
4895         numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
4896         numsurfaces = rtlight->cached_numsurfaces;
4897         lightentities = rtlight->cached_lightentities;
4898         lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
4899         shadowentities = rtlight->cached_shadowentities;
4900         shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
4901         shadowtrispvs = rtlight->cached_shadowtrispvs;
4902         lighttrispvs = rtlight->cached_lighttrispvs;
4903         surfacelist = rtlight->cached_surfacelist;
4904         castshadows = rtlight->castshadows;
4905
4906         // make this the active rtlight for rendering purposes
4907         R_Shadow_RenderMode_ActiveLight(rtlight);
4908
4909         if (r_showshadowvolumes.integer && r_refdef.view.showdebug && numsurfaces + numshadowentities + numshadowentities_noselfshadow && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows))
4910         {
4911                 // optionally draw visible shape of the shadow volumes
4912                 // for performance analysis by level designers
4913                 R_Shadow_RenderMode_VisibleShadowVolumes();
4914                 if (numsurfaces)
4915                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
4916                 for (i = 0;i < numshadowentities;i++)
4917                         R_Shadow_DrawEntityShadow(shadowentities[i]);
4918                 for (i = 0;i < numshadowentities_noselfshadow;i++)
4919                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
4920                 R_Shadow_RenderMode_VisibleLighting(false, false);
4921         }
4922
4923         if (r_showlighting.integer && r_refdef.view.showdebug && numsurfaces + numlightentities + numlightentities_noselfshadow)
4924         {
4925                 // optionally draw the illuminated areas
4926                 // for performance analysis by level designers
4927                 R_Shadow_RenderMode_VisibleLighting(false, false);
4928                 if (numsurfaces)
4929                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
4930                 for (i = 0;i < numlightentities;i++)
4931                         R_Shadow_DrawEntityLight(lightentities[i]);
4932                 for (i = 0;i < numlightentities_noselfshadow;i++)
4933                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
4934         }
4935
4936         if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
4937         {
4938                 float borderbias;
4939                 int size;
4940                 float shadowmapoffsetnoselfshadow = 0;
4941                 matrix4x4_t radiustolight = rtlight->matrix_worldtolight;
4942                 Matrix4x4_Abs(&radiustolight);
4943
4944                 size = rtlight->shadowmapatlassidesize;
4945                 borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
4946
4947                 //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
4948
4949                 if (rtlight->cached_numshadowentities_noselfshadow)
4950                         shadowmapoffsetnoselfshadow = rtlight->shadowmapatlassidesize * 2;
4951
4952                 // render lighting using the depth texture as shadowmap
4953                 // draw lighting in the unmasked areas
4954                 if (numsurfaces + numlightentities)
4955                 {
4956                         R_Shadow_RenderMode_Lighting(false, false, true, false);
4957                         // draw lighting in the unmasked areas
4958                         if (numsurfaces)
4959                                 R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
4960                         for (i = 0; i < numlightentities; i++)
4961                                 R_Shadow_DrawEntityLight(lightentities[i]);
4962                 }
4963                 // offset to the noselfshadow part of the atlas and draw those too
4964                 if (numlightentities_noselfshadow)
4965                 {
4966                         R_Shadow_RenderMode_Lighting(false, false, true, true);
4967                         for (i = 0; i < numlightentities_noselfshadow; i++)
4968                                 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
4969                 }
4970
4971                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
4972                 if (r_shadow_usingdeferredprepass)
4973                         R_Shadow_RenderMode_DrawDeferredLight(true);
4974         }
4975         else if (castshadows && vid.stencil)
4976         {
4977                 // draw stencil shadow volumes to mask off pixels that are in shadow
4978                 // so that they won't receive lighting
4979                 GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
4980                 R_Shadow_ClearStencil();
4981
4982                 if (numsurfaces)
4983                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
4984                 for (i = 0;i < numshadowentities;i++)
4985                         R_Shadow_DrawEntityShadow(shadowentities[i]);
4986
4987                 // draw lighting in the unmasked areas
4988                 R_Shadow_RenderMode_Lighting(true, false, false, false);
4989                 for (i = 0;i < numlightentities_noselfshadow;i++)
4990                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
4991
4992                 for (i = 0;i < numshadowentities_noselfshadow;i++)
4993                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
4994
4995                 // draw lighting in the unmasked areas
4996                 R_Shadow_RenderMode_Lighting(true, false, false, false);
4997                 if (numsurfaces)
4998                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
4999                 for (i = 0;i < numlightentities;i++)
5000                         R_Shadow_DrawEntityLight(lightentities[i]);
5001
5002                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
5003                 if (r_shadow_usingdeferredprepass)
5004                         R_Shadow_RenderMode_DrawDeferredLight(false);
5005         }
5006         else
5007         {
5008                 // draw lighting in the unmasked areas
5009                 R_Shadow_RenderMode_Lighting(false, false, false, false);
5010                 if (numsurfaces)
5011                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
5012                 for (i = 0;i < numlightentities;i++)
5013                         R_Shadow_DrawEntityLight(lightentities[i]);
5014                 for (i = 0;i < numlightentities_noselfshadow;i++)
5015                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
5016
5017                 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
5018                 if (r_shadow_usingdeferredprepass)
5019                         R_Shadow_RenderMode_DrawDeferredLight(false);
5020         }
5021 }
5022
5023 static void R_Shadow_FreeDeferred(void)
5024 {
5025         R_Mesh_DestroyFramebufferObject(r_shadow_prepassgeometryfbo);
5026         r_shadow_prepassgeometryfbo = 0;
5027
5028         R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusespecularfbo);
5029         r_shadow_prepasslightingdiffusespecularfbo = 0;
5030
5031         R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusefbo);
5032         r_shadow_prepasslightingdiffusefbo = 0;
5033
5034         if (r_shadow_prepassgeometrydepthbuffer)
5035                 R_FreeTexture(r_shadow_prepassgeometrydepthbuffer);
5036         r_shadow_prepassgeometrydepthbuffer = NULL;
5037
5038         if (r_shadow_prepassgeometrynormalmaptexture)
5039                 R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
5040         r_shadow_prepassgeometrynormalmaptexture = NULL;
5041
5042         if (r_shadow_prepasslightingdiffusetexture)
5043                 R_FreeTexture(r_shadow_prepasslightingdiffusetexture);
5044         r_shadow_prepasslightingdiffusetexture = NULL;
5045
5046         if (r_shadow_prepasslightingspeculartexture)
5047                 R_FreeTexture(r_shadow_prepasslightingspeculartexture);
5048         r_shadow_prepasslightingspeculartexture = NULL;
5049 }
5050
5051 void R_Shadow_DrawPrepass(void)
5052 {
5053         int i;
5054         int lnum;
5055         entity_render_t *ent;
5056         float clearcolor[4];
5057
5058         R_Mesh_ResetTextureState();
5059         GL_DepthMask(true);
5060         GL_ColorMask(1,1,1,1);
5061         GL_BlendFunc(GL_ONE, GL_ZERO);
5062         GL_Color(1,1,1,1);
5063         GL_DepthTest(true);
5064         R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5065         Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
5066         GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
5067         if (r_timereport_active)
5068                 R_TimeReport("prepasscleargeom");
5069
5070         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawPrepass)
5071                 r_refdef.scene.worldmodel->DrawPrepass(r_refdef.scene.worldentity);
5072         if (r_timereport_active)
5073                 R_TimeReport("prepassworld");
5074
5075         for (i = 0;i < r_refdef.scene.numentities;i++)
5076         {
5077                 if (!r_refdef.viewcache.entityvisible[i])
5078                         continue;
5079                 ent = r_refdef.scene.entities[i];
5080                 if (ent->model && ent->model->DrawPrepass != NULL)
5081                         ent->model->DrawPrepass(ent);
5082         }
5083
5084         if (r_timereport_active)
5085                 R_TimeReport("prepassmodels");
5086
5087         GL_DepthMask(false);
5088         GL_ColorMask(1,1,1,1);
5089         GL_Color(1,1,1,1);
5090         GL_DepthTest(true);
5091         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5092         Vector4Set(clearcolor, 0, 0, 0, 0);
5093         GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
5094         if (r_timereport_active)
5095                 R_TimeReport("prepassclearlit");
5096
5097         R_Shadow_RenderMode_Begin();
5098
5099         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5100                 R_Shadow_DrawLight(r_shadow_scenelightlist[lnum]);
5101
5102         R_Shadow_RenderMode_End();
5103
5104         if (r_timereport_active)
5105                 R_TimeReport("prepasslights");
5106 }
5107
5108 #define MAX_SCENELIGHTS 65536
5109 qboolean R_Shadow_PrepareLights_AddSceneLight(rtlight_t *rtlight)
5110 {
5111         if (r_shadow_scenemaxlights <= r_shadow_scenenumlights)
5112         {
5113                 if (r_shadow_scenenumlights >= MAX_SCENELIGHTS)
5114                         return false;
5115                 r_shadow_scenemaxlights *= 2;
5116                 r_shadow_scenemaxlights = bound(1024, r_shadow_scenemaxlights, MAX_SCENELIGHTS);
5117                 r_shadow_scenelightlist = (rtlight_t **)Mem_Realloc(r_main_mempool, r_shadow_scenelightlist, r_shadow_scenemaxlights * sizeof(rtlight_t *));
5118         }
5119         r_shadow_scenelightlist[r_shadow_scenenumlights++] = rtlight;
5120         return true;
5121 }
5122
5123 void R_Shadow_DrawLightSprites(void);
5124 void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5125 {
5126         int flag;
5127         int lnum;
5128         size_t lightindex;
5129         dlight_t *light;
5130         size_t range;
5131         float f;
5132
5133         int shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
5134         int shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
5135         int shadowmapmaxsize = bound(shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, shadowmaptexturesize / 8);
5136
5137         if (r_shadow_shadowmaptexturesize != shadowmaptexturesize ||
5138                 (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
5139                 r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) ||
5140                 r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
5141                 r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
5142                 r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
5143                 r_shadow_shadowmapborder != shadowmapborder ||
5144                 r_shadow_shadowmapmaxsize != shadowmapmaxsize ||
5145                 r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
5146                 R_Shadow_FreeShadowMaps();
5147
5148         r_shadow_fb_fbo = fbo;
5149         r_shadow_fb_depthtexture = depthtexture;
5150         r_shadow_fb_colortexture = colortexture;
5151
5152         r_shadow_usingshadowmaportho = false;
5153
5154         switch (vid.renderpath)
5155         {
5156         case RENDERPATH_GL20:
5157         case RENDERPATH_D3D9:
5158         case RENDERPATH_D3D10:
5159         case RENDERPATH_D3D11:
5160         case RENDERPATH_SOFT:
5161 #ifndef USE_GLES2
5162                 if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
5163                 {
5164                         r_shadow_usingdeferredprepass = false;
5165                         if (r_shadow_prepass_width)
5166                                 R_Shadow_FreeDeferred();
5167                         r_shadow_prepass_width = r_shadow_prepass_height = 0;
5168                         break;
5169                 }
5170
5171                 if (r_shadow_prepass_width != vid.width || r_shadow_prepass_height != vid.height)
5172                 {
5173                         R_Shadow_FreeDeferred();
5174
5175                         r_shadow_usingdeferredprepass = true;
5176                         r_shadow_prepass_width = vid.width;
5177                         r_shadow_prepass_height = vid.height;
5178                         r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
5179                         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);
5180                         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);
5181                         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);
5182
5183                         // set up the geometry pass fbo (depth + normalmap)
5184                         r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5185                         R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
5186                         // render depth into a renderbuffer and other important properties into the normalmap texture
5187
5188                         // set up the lighting pass fbo (diffuse + specular)
5189                         r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5190                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
5191                         // render diffuse into one texture and specular into another,
5192                         // with depth and normalmap bound as textures,
5193                         // with depth bound as attachment as well
5194
5195                         // set up the lighting pass fbo (diffuse)
5196                         r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5197                         R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
5198                         // render diffuse into one texture,
5199                         // with depth and normalmap bound as textures,
5200                         // with depth bound as attachment as well
5201                 }
5202 #endif
5203                 break;
5204         case RENDERPATH_GL11:
5205         case RENDERPATH_GL13:
5206         case RENDERPATH_GLES1:
5207         case RENDERPATH_GLES2:
5208                 r_shadow_usingdeferredprepass = false;
5209                 break;
5210         }
5211
5212         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);
5213
5214         r_shadow_scenenumlights = 0;
5215         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
5216         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5217         for (lightindex = 0; lightindex < range; lightindex++)
5218         {
5219                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5220                 if (light && (light->flags & flag))
5221                 {
5222                         R_Shadow_PrepareLight(&light->rtlight);
5223                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5224                 }
5225         }
5226         if (r_refdef.scene.rtdlight)
5227         {
5228                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5229                 {
5230                         R_Shadow_PrepareLight(r_refdef.scene.lights[lnum]);
5231                         R_Shadow_PrepareLights_AddSceneLight(r_refdef.scene.lights[lnum]);
5232                 }
5233         }
5234         else if (gl_flashblend.integer)
5235         {
5236                 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
5237                 {
5238                         rtlight_t *rtlight = r_refdef.scene.lights[lnum];
5239                         f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
5240                         VectorScale(rtlight->color, f, rtlight->currentcolor);
5241                 }
5242         }
5243
5244         // when debugging a single light, we still want to run the prepare, so we only replace the light list afterward...
5245         if (r_shadow_debuglight.integer >= 0)
5246         {
5247                 r_shadow_scenenumlights = 0;
5248                 lightindex = r_shadow_debuglight.integer;
5249                 light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5250                 if (light)
5251                 {
5252                         R_Shadow_PrepareLight(&light->rtlight);
5253                         R_Shadow_PrepareLights_AddSceneLight(&light->rtlight);
5254                 }
5255         }
5256
5257         // if we're doing shadowmaps we need to prepare the atlas layout now
5258         if (R_Shadow_ShadowMappingEnabled())
5259         {
5260                 int lod;
5261
5262                 // allocate shadowmaps in the atlas now
5263                 // 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...
5264                 for (lod = 0; lod < 16; lod++)
5265                 {
5266                         int packing_success = 0;
5267                         int packing_failure = 0;
5268                         Mod_AllocLightmap_Reset(&r_shadow_shadowmapatlas_state);
5269                         // we actually have to reserve space for the R_DrawModelShadowMaps if that feature is active, it uses 0,0 so this is easy.
5270                         if (r_shadow_shadowmapatlas_modelshadows_size)
5271                                 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);
5272                         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5273                         {
5274                                 rtlight_t *rtlight = r_shadow_scenelightlist[lnum];
5275                                 int size = rtlight->shadowmapsidesize >> lod;
5276                                 int width, height;
5277                                 if (!rtlight->castshadows)
5278                                         continue;
5279                                 size = bound(r_shadow_shadowmapborder, size, r_shadow_shadowmaptexturesize);
5280                                 width = size * 2;
5281                                 height = size * 3;
5282                                 // when there are noselfshadow entities in the light bounds, we have to render two separate sets of shadowmaps :(
5283                                 if (rtlight->cached_numshadowentities_noselfshadow)
5284                                         width *= 2;
5285                                 if (Mod_AllocLightmap_Block(&r_shadow_shadowmapatlas_state, width, height, &rtlight->shadowmapatlasposition[0], &rtlight->shadowmapatlasposition[1]))
5286                                 {
5287                                         rtlight->shadowmapatlassidesize = size;
5288                                         packing_success++;
5289                                 }
5290                                 else
5291                                 {
5292                                         // note down that we failed to pack this one, it will have to disable shadows
5293                                         rtlight->shadowmapatlassidesize = 0;
5294                                         packing_failure++;
5295                                 }
5296                         }
5297                         // generally everything fits and we stop here on the first iteration
5298                         if (packing_failure == 0)
5299                                 break;
5300                 }
5301         }
5302
5303         if (r_editlights.integer)
5304                 R_Shadow_DrawLightSprites();
5305 }
5306
5307 void R_Shadow_DrawShadowMaps(void)
5308 {
5309         R_Shadow_RenderMode_Begin();
5310         R_Shadow_RenderMode_ActiveLight(NULL);
5311
5312         // now that we have a layout of shadowmaps in the atlas, we can render the shadowmaps
5313         R_Shadow_ClearShadowMapTexture();
5314
5315         // render model shadowmaps (r_shadows 2) if desired which will be sampled in the forward pass
5316         if (r_shadow_shadowmapatlas_modelshadows_size)
5317         {
5318                 R_Shadow_DrawModelShadowMaps();
5319                 // don't let sound skip if going slow
5320                 if (r_refdef.scene.extraupdate)
5321                         S_ExtraUpdate();
5322         }
5323
5324         if (R_Shadow_ShadowMappingEnabled())
5325         {
5326                 int lnum;
5327                 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5328                         R_Shadow_DrawLightShadowMaps(r_shadow_scenelightlist[lnum]);
5329         }
5330
5331         R_Shadow_RenderMode_End();
5332 }
5333
5334 void R_Shadow_DrawLights(void)
5335 {
5336         int lnum;
5337
5338         R_Shadow_RenderMode_Begin();
5339
5340         for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
5341                 R_Shadow_DrawLight(r_shadow_scenelightlist[lnum]);
5342
5343         R_Shadow_RenderMode_End();
5344 }
5345
5346 #define MAX_MODELSHADOWS 1024
5347 static int r_shadow_nummodelshadows;
5348 static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS];
5349
5350 void R_Shadow_PrepareModelShadows(void)
5351 {
5352         int i;
5353         float scale, size, radius, dot1, dot2;
5354         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5355         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
5356         entity_render_t *ent;
5357
5358         r_shadow_nummodelshadows = 0;
5359         r_shadow_shadowmapatlas_modelshadows_size = 0;
5360
5361         if (!r_refdef.scene.numentities || r_refdef.lightmapintensity <= 0.0f || r_shadows.integer <= 0)
5362                 return;
5363
5364         switch (r_shadow_shadowmode)
5365         {
5366         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
5367                 if (r_shadows.integer >= 2)
5368                         break;
5369                 // fall through
5370         case R_SHADOW_SHADOWMODE_STENCIL:
5371                 if (!vid.stencil)
5372                         return;
5373                 for (i = 0; i < r_refdef.scene.numentities; i++)
5374                 {
5375                         ent = r_refdef.scene.entities[i];
5376                         if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5377                         {
5378                                 if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5379                                         break;
5380                                 r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5381                                 R_AnimCache_GetEntity(ent, false, false);
5382                         }
5383                 }
5384                 return;
5385         default:
5386                 return;
5387         }
5388
5389         size = 2 * r_shadow_shadowmapmaxsize;
5390         scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
5391         radius = 0.5f * size / scale;
5392
5393         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5394         VectorCopy(prvmshadowdir, shadowdir);
5395         VectorNormalize(shadowdir);
5396         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5397         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5398         if (fabs(dot1) <= fabs(dot2))
5399                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5400         else
5401                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5402         VectorNormalize(shadowforward);
5403         CrossProduct(shadowdir, shadowforward, shadowright);
5404         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5405         VectorCopy(prvmshadowfocus, shadowfocus);
5406         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5407         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5408         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5409         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5410         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5411                 dot1 = 1;
5412         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5413
5414         shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5415         shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5416         shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5417         shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
5418         shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
5419         shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
5420
5421         for (i = 0; i < r_refdef.scene.numentities; i++)
5422         {
5423                 ent = r_refdef.scene.entities[i];
5424                 if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
5425                         continue;
5426                 // cast shadows from anything of the map (submodels are optional)
5427                 if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
5428                 {
5429                         if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
5430                                 break;
5431                         r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
5432                         R_AnimCache_GetEntity(ent, false, false);
5433                 }
5434         }
5435
5436         if (r_shadow_nummodelshadows)
5437         {
5438                 r_shadow_shadowmapatlas_modelshadows_x = 0;
5439                 r_shadow_shadowmapatlas_modelshadows_y = 0;
5440                 r_shadow_shadowmapatlas_modelshadows_size = size;
5441         }
5442 }
5443
5444 static void R_Shadow_DrawModelShadowMaps(void)
5445 {
5446         int i;
5447         float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
5448         entity_render_t *ent;
5449         vec3_t relativelightorigin;
5450         vec3_t relativelightdirection, relativeforward, relativeright;
5451         vec3_t relativeshadowmins, relativeshadowmaxs;
5452         vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
5453         prvm_vec3_t prvmshadowdir, prvmshadowfocus;
5454         float m[12];
5455         matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
5456         r_viewport_t viewport;
5457
5458         size = r_shadow_shadowmapatlas_modelshadows_size;
5459         scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size;
5460         radius = 0.5f / scale;
5461         nearclip = -r_shadows_throwdistance.value;
5462         farclip = r_shadows_throwdistance.value;
5463         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);
5464
5465         // set the parameters that will be used on the regular model renders using these shadows we're about to produce
5466         r_shadow_modelshadowmap_parameters[0] = size;
5467         r_shadow_modelshadowmap_parameters[1] = size;
5468         r_shadow_modelshadowmap_parameters[2] = 1.0;
5469         r_shadow_modelshadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
5470         r_shadow_modelshadowmap_texturescale[0] = 1.0f / r_shadow_shadowmaptexturesize;
5471         r_shadow_modelshadowmap_texturescale[1] = 1.0f / r_shadow_shadowmaptexturesize;
5472         r_shadow_modelshadowmap_texturescale[2] = r_shadow_shadowmapatlas_modelshadows_x;
5473         r_shadow_modelshadowmap_texturescale[3] = r_shadow_shadowmapatlas_modelshadows_y;
5474         r_shadow_usingshadowmaportho = true;
5475
5476         Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5477         VectorCopy(prvmshadowdir, shadowdir);
5478         VectorNormalize(shadowdir);
5479         Math_atov(r_shadows_focus.string, prvmshadowfocus);
5480         VectorCopy(prvmshadowfocus, shadowfocus);
5481         VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
5482         VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
5483         VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
5484         VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
5485         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
5486         dot2 = DotProduct(r_refdef.view.up, shadowdir);
5487         if (fabs(dot1) <= fabs(dot2)) 
5488                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
5489         else
5490                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
5491         VectorNormalize(shadowforward);
5492         VectorM(scale, shadowforward, &m[0]);
5493         if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
5494                 dot1 = 1;
5495         m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
5496         CrossProduct(shadowdir, shadowforward, shadowright);
5497         VectorM(scale, shadowright, &m[4]);
5498         m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
5499         VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
5500         m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
5501         Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
5502         Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
5503         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);
5504         R_SetViewport(&viewport);
5505
5506         VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
5507
5508         // render into a slightly restricted region so that the borders of the
5509         // shadowmap area fade away, rather than streaking across everything
5510         // outside the usable area
5511         GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
5512
5513         for (i = 0;i < r_shadow_nummodelshadows;i++)
5514         {
5515                 ent = r_shadow_modelshadows[i];
5516                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5517                 Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
5518                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5519                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
5520                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
5521                 relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5522                 relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5523                 relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5524                 relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
5525                 relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
5526                 relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
5527                 RSurf_ActiveModelEntity(ent, false, false, false);
5528                 ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
5529                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5530         }
5531
5532 #if 0
5533         if (r_test.integer)
5534         {
5535                 unsigned char *rawpixels = Z_Malloc(viewport.width*viewport.height*4);
5536                 CHECKGLERROR
5537                 qglReadPixels(viewport.x, viewport.y, viewport.width, viewport.height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, rawpixels);
5538                 CHECKGLERROR
5539                 Image_WriteTGABGRA("r_shadows_2.tga", viewport.width, viewport.height, rawpixels);
5540                 Cvar_SetValueQuick(&r_test, 0);
5541                 Z_Free(rawpixels);
5542         }
5543 #endif
5544
5545         Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5546         Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5547         Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); 
5548         Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
5549         Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
5550         Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
5551
5552         switch (vid.renderpath)
5553         {
5554         case RENDERPATH_GL11:
5555         case RENDERPATH_GL13:
5556         case RENDERPATH_GL20:
5557         case RENDERPATH_SOFT:
5558         case RENDERPATH_GLES1:
5559         case RENDERPATH_GLES2:
5560                 break;
5561         case RENDERPATH_D3D9:
5562         case RENDERPATH_D3D10:
5563         case RENDERPATH_D3D11:
5564 #ifdef MATRIX4x4_OPENGLORIENTATION
5565                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5566                 r_shadow_shadowmapmatrix.m[0][1]        *= -1.0f;
5567                 r_shadow_shadowmapmatrix.m[0][2]        *= -1.0f;
5568                 r_shadow_shadowmapmatrix.m[0][3]        *= -1.0f;
5569 #else
5570                 r_shadow_shadowmapmatrix.m[0][0]        *= -1.0f;
5571                 r_shadow_shadowmapmatrix.m[1][0]        *= -1.0f;
5572                 r_shadow_shadowmapmatrix.m[2][0]        *= -1.0f;
5573                 r_shadow_shadowmapmatrix.m[3][0]        *= -1.0f;
5574 #endif
5575                 break;
5576         }
5577 }
5578
5579 void R_Shadow_DrawModelShadows(void)
5580 {
5581         int i;
5582         float relativethrowdistance;
5583         entity_render_t *ent;
5584         vec3_t relativelightorigin;
5585         vec3_t relativelightdirection;
5586         vec3_t relativeshadowmins, relativeshadowmaxs;
5587         vec3_t tmp, shadowdir;
5588         prvm_vec3_t prvmshadowdir;
5589
5590         if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
5591                 return;
5592
5593         R_ResetViewRendering3D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5594         //GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5595         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5596         R_Shadow_RenderMode_Begin();
5597         R_Shadow_RenderMode_ActiveLight(NULL);
5598         r_shadow_lightscissor[0] = r_refdef.view.x;
5599         r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
5600         r_shadow_lightscissor[2] = r_refdef.view.width;
5601         r_shadow_lightscissor[3] = r_refdef.view.height;
5602         R_Shadow_RenderMode_StencilShadowVolumes(false);
5603
5604         // get shadow dir
5605         if (r_shadows.integer == 2)
5606         {
5607                 Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
5608                 VectorCopy(prvmshadowdir, shadowdir);
5609                 VectorNormalize(shadowdir);
5610         }
5611
5612         R_Shadow_ClearStencil();
5613
5614         for (i = 0;i < r_shadow_nummodelshadows;i++)
5615         {
5616                 ent = r_shadow_modelshadows[i];
5617
5618                 // cast shadows from anything of the map (submodels are optional)
5619                 relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
5620                 VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
5621                 VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
5622                 if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
5623                         Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
5624                 else
5625                 {
5626                         if(ent->entitynumber != 0)
5627                         {
5628                                 if(ent->entitynumber >= MAX_EDICTS) // csqc entity
5629                                 {
5630                                         // FIXME handle this
5631                                         VectorNegate(ent->modellight_lightdir, relativelightdirection);
5632                                 }
5633                                 else
5634                                 {
5635                                         // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
5636                                         int entnum, entnum2, recursion;
5637                                         entnum = entnum2 = ent->entitynumber;
5638                                         for(recursion = 32; recursion > 0; --recursion)
5639                                         {
5640                                                 entnum2 = cl.entities[entnum].state_current.tagentity;
5641                                                 if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
5642                                                         entnum = entnum2;
5643                                                 else
5644                                                         break;
5645                                         }
5646                                         if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
5647                                         {
5648                                                 VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
5649                                                 // transform into modelspace of OUR entity
5650                                                 Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
5651                                                 Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
5652                                         }
5653                                         else
5654                                                 VectorNegate(ent->modellight_lightdir, relativelightdirection);
5655                                 }
5656                         }
5657                         else
5658                                 VectorNegate(ent->modellight_lightdir, relativelightdirection);
5659                 }
5660
5661                 VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
5662                 RSurf_ActiveModelEntity(ent, false, false, false);
5663                 ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
5664                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5665         }
5666
5667         // not really the right mode, but this will disable any silly stencil features
5668         R_Shadow_RenderMode_End();
5669
5670         // set up ortho view for rendering this pass
5671         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
5672         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5673         //GL_ScissorTest(true);
5674         //R_EntityMatrix(&identitymatrix);
5675         //R_Mesh_ResetTextureState();
5676         R_ResetViewRendering2D(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture);
5677
5678         // set up a darkening blend on shadowed areas
5679         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5680         //GL_DepthRange(0, 1);
5681         //GL_DepthTest(false);
5682         //GL_DepthMask(false);
5683         //GL_PolygonOffset(0, 0);CHECKGLERROR
5684         GL_Color(0, 0, 0, r_shadows_darken.value);
5685         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5686         //GL_DepthFunc(GL_ALWAYS);
5687         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_NOTEQUAL, 128, 255);
5688
5689         // apply the blend to the shadowed areas
5690         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
5691         R_SetupShader_Generic_NoTexture(false, true);
5692         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5693
5694         // restore the viewport
5695         R_SetViewport(&r_refdef.view.viewport);
5696
5697         // restore other state to normal
5698         //R_Shadow_RenderMode_End();
5699 }
5700
5701 static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
5702 {
5703         float zdist;
5704         vec3_t centerorigin;
5705 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5706         float vertex3f[12];
5707 #endif
5708         // if it's too close, skip it
5709         if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
5710                 return;
5711         zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
5712         if (zdist < 32)
5713                 return;
5714         if (usequery && r_numqueries + 2 <= r_maxqueries)
5715         {
5716                 rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
5717                 rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
5718                 // 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
5719                 VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
5720
5721                 switch(vid.renderpath)
5722                 {
5723                 case RENDERPATH_GL11:
5724                 case RENDERPATH_GL13:
5725                 case RENDERPATH_GL20:
5726                 case RENDERPATH_GLES1:
5727                 case RENDERPATH_GLES2:
5728 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5729                         CHECKGLERROR
5730                         // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
5731                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
5732                         GL_DepthFunc(GL_ALWAYS);
5733                         R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5734                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5735                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5736                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5737                         GL_DepthFunc(GL_LEQUAL);
5738                         qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
5739                         R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5740                         R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
5741                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5742                         qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
5743                         CHECKGLERROR
5744 #endif
5745                         break;
5746                 case RENDERPATH_D3D9:
5747                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5748                         break;
5749                 case RENDERPATH_D3D10:
5750                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5751                         break;
5752                 case RENDERPATH_D3D11:
5753                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5754                         break;
5755                 case RENDERPATH_SOFT:
5756                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5757                         break;
5758                 }
5759         }
5760         rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
5761 }
5762
5763 static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5764
5765 static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
5766 {
5767         vec3_t color;
5768         unsigned int occlude = 0;
5769         GLint allpixels = 0, visiblepixels = 0;
5770
5771         // now we have to check the query result
5772         if (rtlight->corona_queryindex_visiblepixels)
5773         {
5774                 switch(vid.renderpath)
5775                 {
5776                 case RENDERPATH_GL11:
5777                 case RENDERPATH_GL13:
5778                 case RENDERPATH_GL20:
5779                 case RENDERPATH_GLES1:
5780                 case RENDERPATH_GLES2:
5781 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5782                         CHECKGLERROR
5783                         // See if we can use the GPU-side method to prevent implicit sync
5784                         if (vid.support.arb_query_buffer_object) {
5785 #define BUFFER_OFFSET(i)    ((GLint *)((unsigned char*)NULL + (i)))
5786                                 if (!r_shadow_occlusion_buf) {
5787                                         qglGenBuffersARB(1, &r_shadow_occlusion_buf);
5788                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5789                                         qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
5790                                 } else {
5791                                         qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
5792                                 }
5793                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
5794                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
5795                                 qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
5796                                 occlude = MATERIALFLAG_OCCLUDE;
5797                         } else {
5798                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
5799                                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels); 
5800                                 if (visiblepixels < 1 || allpixels < 1)
5801                                         return;
5802                                 rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
5803                         }
5804                         cscale *= rtlight->corona_visibility;
5805                         CHECKGLERROR
5806                         break;
5807 #else
5808                         return;
5809 #endif
5810                 case RENDERPATH_D3D9:
5811                         Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5812                         return;
5813                 case RENDERPATH_D3D10:
5814                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5815                         return;
5816                 case RENDERPATH_D3D11:
5817                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5818                         return;
5819                 case RENDERPATH_SOFT:
5820                         //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5821                         return;
5822                 default:
5823                         return;
5824                 }
5825         }
5826         else
5827         {
5828                 // FIXME: these traces should scan all render entities instead of cl.world
5829                 if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
5830                         return;
5831         }
5832         VectorScale(rtlight->currentcolor, cscale, color);
5833         if (VectorLength(color) > (1.0f / 256.0f))
5834         {
5835                 float vertex3f[12];
5836                 qboolean negated = (color[0] + color[1] + color[2] < 0) && vid.support.ext_blend_subtract;
5837                 if(negated)
5838                 {
5839                         VectorNegate(color, color);
5840                         GL_BlendEquationSubtract(true);
5841                 }
5842                 R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
5843                 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);
5844                 R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false);
5845                 if(negated)
5846                         GL_BlendEquationSubtract(false);
5847         }
5848 }
5849
5850 void R_Shadow_DrawCoronas(void)
5851 {
5852         int i, flag;
5853         qboolean usequery = false;
5854         size_t lightindex;
5855         dlight_t *light;
5856         rtlight_t *rtlight;
5857         size_t range;
5858         if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
5859                 return;
5860         if (r_fb.water.renderingscene)
5861                 return;
5862         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
5863         R_EntityMatrix(&identitymatrix);
5864
5865         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5866
5867         // check occlusion of coronas
5868         // use GL_ARB_occlusion_query if available
5869         // otherwise use raytraces
5870         r_numqueries = 0;
5871         switch (vid.renderpath)
5872         {
5873         case RENDERPATH_GL11:
5874         case RENDERPATH_GL13:
5875         case RENDERPATH_GL20:
5876         case RENDERPATH_GLES1:
5877         case RENDERPATH_GLES2:
5878                 usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
5879 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
5880                 if (usequery)
5881                 {
5882                         GL_ColorMask(0,0,0,0);
5883                         if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
5884                         if (r_maxqueries < MAX_OCCLUSION_QUERIES)
5885                         {
5886                                 i = r_maxqueries;
5887                                 r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
5888                                 r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
5889                                 CHECKGLERROR
5890                                 qglGenQueriesARB(r_maxqueries - i, r_queries + i);
5891                                 CHECKGLERROR
5892                         }
5893                         RSurf_ActiveWorldEntity();
5894                         GL_BlendFunc(GL_ONE, GL_ZERO);
5895                         GL_CullFace(GL_NONE);
5896                         GL_DepthMask(false);
5897                         GL_DepthRange(0, 1);
5898                         GL_PolygonOffset(0, 0);
5899                         GL_DepthTest(true);
5900                         R_Mesh_ResetTextureState();
5901                         R_SetupShader_Generic_NoTexture(false, false);
5902                 }
5903 #endif
5904                 break;
5905         case RENDERPATH_D3D9:
5906                 usequery = false;
5907                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5908                 break;
5909         case RENDERPATH_D3D10:
5910                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5911                 break;
5912         case RENDERPATH_D3D11:
5913                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5914                 break;
5915         case RENDERPATH_SOFT:
5916                 usequery = false;
5917                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5918                 break;
5919         }
5920         for (lightindex = 0;lightindex < range;lightindex++)
5921         {
5922                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5923                 if (!light)
5924                         continue;
5925                 rtlight = &light->rtlight;
5926                 rtlight->corona_visibility = 0;
5927                 rtlight->corona_queryindex_visiblepixels = 0;
5928                 rtlight->corona_queryindex_allpixels = 0;
5929                 if (!(rtlight->flags & flag))
5930                         continue;
5931                 if (rtlight->corona <= 0)
5932                         continue;
5933                 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex)
5934                         continue;
5935                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
5936         }
5937         for (i = 0;i < r_refdef.scene.numlights;i++)
5938         {
5939                 rtlight = r_refdef.scene.lights[i];
5940                 rtlight->corona_visibility = 0;
5941                 rtlight->corona_queryindex_visiblepixels = 0;
5942                 rtlight->corona_queryindex_allpixels = 0;
5943                 if (!(rtlight->flags & flag))
5944                         continue;
5945                 if (rtlight->corona <= 0)
5946                         continue;
5947                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
5948         }
5949         if (usequery)
5950                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5951
5952         // now draw the coronas using the query data for intensity info
5953         for (lightindex = 0;lightindex < range;lightindex++)
5954         {
5955                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5956                 if (!light)
5957                         continue;
5958                 rtlight = &light->rtlight;
5959                 if (rtlight->corona_visibility <= 0)
5960                         continue;
5961                 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
5962         }
5963         for (i = 0;i < r_refdef.scene.numlights;i++)
5964         {
5965                 rtlight = r_refdef.scene.lights[i];
5966                 if (rtlight->corona_visibility <= 0)
5967                         continue;
5968                 if (gl_flashblend.integer)
5969                         R_DrawCorona(rtlight, rtlight->corona, rtlight->radius * rtlight->coronasizescale * 2.0f);
5970                 else
5971                         R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
5972         }
5973 }
5974
5975
5976
5977 static dlight_t *R_Shadow_NewWorldLight(void)
5978 {
5979         return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
5980 }
5981
5982 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)
5983 {
5984         matrix4x4_t matrix;
5985
5986         // 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
5987
5988         // validate parameters
5989         if (!cubemapname)
5990                 cubemapname = "";
5991
5992         // copy to light properties
5993         VectorCopy(origin, light->origin);
5994         light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
5995         light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
5996         light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
5997         /*
5998         light->color[0] = max(color[0], 0);
5999         light->color[1] = max(color[1], 0);
6000         light->color[2] = max(color[2], 0);
6001         */
6002         light->color[0] = color[0];
6003         light->color[1] = color[1];
6004         light->color[2] = color[2];
6005         light->radius = max(radius, 0);
6006         light->style = style;
6007         light->shadow = shadowenable;
6008         light->corona = corona;
6009         strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
6010         light->coronasizescale = coronasizescale;
6011         light->ambientscale = ambientscale;
6012         light->diffusescale = diffusescale;
6013         light->specularscale = specularscale;
6014         light->flags = flags;
6015
6016         // update renderable light data
6017         Matrix4x4_CreateFromQuakeEntity(&matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], light->radius);
6018         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);
6019 }
6020
6021 static void R_Shadow_FreeWorldLight(dlight_t *light)
6022 {
6023         if (r_shadow_selectedlight == light)
6024                 r_shadow_selectedlight = NULL;
6025         R_RTLight_Uncompile(&light->rtlight);
6026         Mem_ExpandableArray_FreeRecord(&r_shadow_worldlightsarray, light);
6027 }
6028
6029 void R_Shadow_ClearWorldLights(void)
6030 {
6031         size_t lightindex;
6032         dlight_t *light;
6033         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6034         for (lightindex = 0;lightindex < range;lightindex++)
6035         {
6036                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6037                 if (light)
6038                         R_Shadow_FreeWorldLight(light);
6039         }
6040         r_shadow_selectedlight = NULL;
6041 }
6042
6043 static void R_Shadow_SelectLight(dlight_t *light)
6044 {
6045         if (r_shadow_selectedlight)
6046                 r_shadow_selectedlight->selected = false;
6047         r_shadow_selectedlight = light;
6048         if (r_shadow_selectedlight)
6049                 r_shadow_selectedlight->selected = true;
6050 }
6051
6052 static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6053 {
6054         // this is never batched (there can be only one)
6055         float vertex3f[12];
6056         R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
6057         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6058         R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6059 }
6060
6061 static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6062 {
6063         float intensity;
6064         float s;
6065         vec3_t spritecolor;
6066         skinframe_t *skinframe;
6067         float vertex3f[12];
6068
6069         // this is never batched (due to the ent parameter changing every time)
6070         // so numsurfaces == 1 and surfacelist[0] == lightnumber
6071         const dlight_t *light = (dlight_t *)ent;
6072         s = EDLIGHTSPRSIZE;
6073
6074         R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
6075
6076         intensity = 0.5f;
6077         VectorScale(light->color, intensity, spritecolor);
6078         if (VectorLength(spritecolor) < 0.1732f)
6079                 VectorSet(spritecolor, 0.1f, 0.1f, 0.1f);
6080         if (VectorLength(spritecolor) > 1.0f)
6081                 VectorNormalize(spritecolor);
6082
6083         // draw light sprite
6084         if (light->cubemapname[0] && !light->shadow)
6085                 skinframe = r_editlights_sprcubemapnoshadowlight;
6086         else if (light->cubemapname[0])
6087                 skinframe = r_editlights_sprcubemaplight;
6088         else if (!light->shadow)
6089                 skinframe = r_editlights_sprnoshadowlight;
6090         else
6091                 skinframe = r_editlights_sprlight;
6092
6093         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);
6094         R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6095
6096         // draw selection sprite if light is selected
6097         if (light->selected)
6098         {
6099                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
6100                 R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
6101                 // VorteX todo: add normalmode/realtime mode light overlay sprites?
6102         }
6103 }
6104
6105 void R_Shadow_DrawLightSprites(void)
6106 {
6107         size_t lightindex;
6108         dlight_t *light;
6109         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6110         for (lightindex = 0;lightindex < range;lightindex++)
6111         {
6112                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6113                 if (light)
6114                         R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
6115         }
6116         if (!r_editlights_lockcursor)
6117                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
6118 }
6119
6120 int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
6121 {
6122         unsigned int range;
6123         dlight_t *light;
6124         rtlight_t *rtlight;
6125         range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
6126         if (lightindex >= range)
6127                 return -1;
6128         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6129         if (!light)
6130                 return 0;
6131         rtlight = &light->rtlight;
6132         //if (!(rtlight->flags & flag))
6133         //      return 0;
6134         VectorCopy(rtlight->shadoworigin, origin);
6135         *radius = rtlight->radius;
6136         VectorCopy(rtlight->color, color);
6137         return 1;
6138 }
6139
6140 static void R_Shadow_SelectLightInView(void)
6141 {
6142         float bestrating, rating, temp[3];
6143         dlight_t *best;
6144         size_t lightindex;
6145         dlight_t *light;
6146         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
6147         best = NULL;
6148         bestrating = 0;
6149
6150         if (r_editlights_lockcursor)
6151                 return;
6152         for (lightindex = 0;lightindex < range;lightindex++)
6153         {
6154                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6155                 if (!light)
6156                         continue;
6157                 VectorSubtract(light->origin, r_refdef.view.origin, temp);
6158                 rating = (DotProduct(temp, r_refdef.view.forward) / sqrt(DotProduct(temp, temp)));
6159                 if (rating >= 0.95)
6160                 {
6161                         rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
6162                         if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f)
6163                         {
6164                                 bestrating = rating;
6165                                 best = light;
6166                         }
6167                 }
6168         }
6169         R_Shadow_SelectLight(best);
6170 }
6171
6172 void R_Shadow_LoadWorldLights(void)
6173 {
6174         int n, a, style, shadow, flags;
6175         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
6176         float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
6177         if (cl.worldmodel == NULL)
6178         {
6179                 Con_Print("No map loaded.\n");
6180                 return;
6181         }
6182         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6183         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6184         if (lightsstring)
6185         {
6186                 s = lightsstring;
6187                 n = 0;
6188                 while (*s)
6189                 {
6190                         /*
6191                         t = s;
6192                         shadow = true;
6193                         for (;COM_Parse(t, true) && strcmp(
6194                         if (COM_Parse(t, true))
6195                         {
6196                                 if (com_token[0] == '!')
6197                                 {
6198                                         shadow = false;
6199                                         origin[0] = atof(com_token+1);
6200                                 }
6201                                 else
6202                                         origin[0] = atof(com_token);
6203                                 if (Com_Parse(t
6204                         }
6205                         */
6206                         t = s;
6207                         while (*s && *s != '\n' && *s != '\r')
6208                                 s++;
6209                         if (!*s)
6210                                 break;
6211                         tempchar = *s;
6212                         shadow = true;
6213                         // check for modifier flags
6214                         if (*t == '!')
6215                         {
6216                                 shadow = false;
6217                                 t++;
6218                         }
6219                         *s = 0;
6220 #if _MSC_VER >= 1400
6221 #define sscanf sscanf_s
6222 #endif
6223                         cubemapname[sizeof(cubemapname)-1] = 0;
6224 #if MAX_QPATH != 128
6225 #error update this code if MAX_QPATH changes
6226 #endif
6227                         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
6228 #if _MSC_VER >= 1400
6229 , sizeof(cubemapname)
6230 #endif
6231 , &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
6232                         *s = tempchar;
6233                         if (a < 18)
6234                                 flags = LIGHTFLAG_REALTIMEMODE;
6235                         if (a < 17)
6236                                 specularscale = 1;
6237                         if (a < 16)
6238                                 diffusescale = 1;
6239                         if (a < 15)
6240                                 ambientscale = 0;
6241                         if (a < 14)
6242                                 coronasizescale = 0.25f;
6243                         if (a < 13)
6244                                 VectorClear(angles);
6245                         if (a < 10)
6246                                 corona = 0;
6247                         if (a < 9 || !strcmp(cubemapname, "\"\""))
6248                                 cubemapname[0] = 0;
6249                         // remove quotes on cubemapname
6250                         if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
6251                         {
6252                                 size_t namelen;
6253                                 namelen = strlen(cubemapname) - 2;
6254                                 memmove(cubemapname, cubemapname + 1, namelen);
6255                                 cubemapname[namelen] = '\0';
6256                         }
6257                         if (a < 8)
6258                         {
6259                                 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);
6260                                 break;
6261                         }
6262                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
6263                         if (*s == '\r')
6264                                 s++;
6265                         if (*s == '\n')
6266                                 s++;
6267                         n++;
6268                 }
6269                 if (*s)
6270                         Con_Printf("invalid rtlights file \"%s\"\n", name);
6271                 Mem_Free(lightsstring);
6272         }
6273 }
6274
6275 void R_Shadow_SaveWorldLights(void)
6276 {
6277         size_t lightindex;
6278         dlight_t *light;
6279         size_t bufchars, bufmaxchars;
6280         char *buf, *oldbuf;
6281         char name[MAX_QPATH];
6282         char line[MAX_INPUTLINE];
6283         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
6284         // I hate lines which are 3 times my screen size :( --blub
6285         if (!range)
6286                 return;
6287         if (cl.worldmodel == NULL)
6288         {
6289                 Con_Print("No map loaded.\n");
6290                 return;
6291         }
6292         dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
6293         bufchars = bufmaxchars = 0;
6294         buf = NULL;
6295         for (lightindex = 0;lightindex < range;lightindex++)
6296         {
6297                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
6298                 if (!light)
6299                         continue;
6300                 if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE)
6301                         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);
6302                 else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
6303                         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]);
6304                 else
6305                         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);
6306                 if (bufchars + strlen(line) > bufmaxchars)
6307                 {
6308                         bufmaxchars = bufchars + strlen(line) + 2048;
6309                         oldbuf = buf;
6310                         buf = (char *)Mem_Alloc(tempmempool, bufmaxchars);
6311                         if (oldbuf)
6312                         {
6313                                 if (bufchars)
6314                                         memcpy(buf, oldbuf, bufchars);
6315                                 Mem_Free(oldbuf);
6316                         }
6317                 }
6318                 if (strlen(line))
6319                 {
6320                         memcpy(buf + bufchars, line, strlen(line));
6321                         bufchars += strlen(line);
6322                 }
6323         }
6324         if (bufchars)
6325                 FS_WriteFile(name, buf, (fs_offset_t)bufchars);
6326         if (buf)
6327                 Mem_Free(buf);
6328 }
6329
6330 void R_Shadow_LoadLightsFile(void)
6331 {
6332         int n, a, style;
6333         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
6334         float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
6335         if (cl.worldmodel == NULL)
6336         {
6337                 Con_Print("No map loaded.\n");
6338                 return;
6339         }
6340         dpsnprintf(name, sizeof(name), "%s.lights", cl.worldnamenoextension);
6341         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
6342         if (lightsstring)
6343         {
6344                 s = lightsstring;
6345                 n = 0;
6346                 while (*s)
6347                 {
6348                         t = s;
6349                         while (*s && *s != '\n' && *s != '\r')
6350                                 s++;
6351                         if (!*s)
6352                                 break;
6353                         tempchar = *s;
6354                         *s = 0;
6355                         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);
6356                         *s = tempchar;
6357                         if (a < 14)
6358                         {
6359                                 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);
6360                                 break;
6361                         }
6362                         radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f));
6363                         radius = bound(15, radius, 4096);
6364                         VectorScale(color, (2.0f / (8388608.0f)), color);
6365                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6366                         if (*s == '\r')
6367                                 s++;
6368                         if (*s == '\n')
6369                                 s++;
6370                         n++;
6371                 }
6372                 if (*s)
6373                         Con_Printf("invalid lights file \"%s\"\n", name);
6374                 Mem_Free(lightsstring);
6375         }
6376 }
6377
6378 // tyrlite/hmap2 light types in the delay field
6379 typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
6380
6381 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
6382 {
6383         int entnum;
6384         int style;
6385         int islight;
6386         int skin;
6387         int pflags;
6388         //int effects;
6389         int type;
6390         int n;
6391         char *entfiledata;
6392         const char *data;
6393         float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
6394         char key[256], value[MAX_INPUTLINE];
6395         char vabuf[1024];
6396
6397         if (cl.worldmodel == NULL)
6398         {
6399                 Con_Print("No map loaded.\n");
6400                 return;
6401         }
6402         // try to load a .ent file first
6403         dpsnprintf(key, sizeof(key), "%s.ent", cl.worldnamenoextension);
6404         data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL);
6405         // and if that is not found, fall back to the bsp file entity string
6406         if (!data)
6407                 data = cl.worldmodel->brush.entities;
6408         if (!data)
6409                 return;
6410         for (entnum = 0;COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{';entnum++)
6411         {
6412                 type = LIGHTTYPE_MINUSX;
6413                 origin[0] = origin[1] = origin[2] = 0;
6414                 originhack[0] = originhack[1] = originhack[2] = 0;
6415                 angles[0] = angles[1] = angles[2] = 0;
6416                 color[0] = color[1] = color[2] = 1;
6417                 light[0] = light[1] = light[2] = 1;light[3] = 300;
6418                 overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
6419                 fadescale = 1;
6420                 lightscale = 1;
6421                 style = 0;
6422                 skin = 0;
6423                 pflags = 0;
6424                 //effects = 0;
6425                 islight = false;
6426                 while (1)
6427                 {
6428                         if (!COM_ParseToken_Simple(&data, false, false, true))
6429                                 break; // error
6430                         if (com_token[0] == '}')
6431                                 break; // end of entity
6432                         if (com_token[0] == '_')
6433                                 strlcpy(key, com_token + 1, sizeof(key));
6434                         else
6435                                 strlcpy(key, com_token, sizeof(key));
6436                         while (key[strlen(key)-1] == ' ') // remove trailing spaces
6437                                 key[strlen(key)-1] = 0;
6438                         if (!COM_ParseToken_Simple(&data, false, false, true))
6439                                 break; // error
6440                         strlcpy(value, com_token, sizeof(value));
6441
6442                         // now that we have the key pair worked out...
6443                         if (!strcmp("light", key))
6444                         {
6445                                 n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
6446                                 if (n == 1)
6447                                 {
6448                                         // quake
6449                                         light[0] = vec[0] * (1.0f / 256.0f);
6450                                         light[1] = vec[0] * (1.0f / 256.0f);
6451                                         light[2] = vec[0] * (1.0f / 256.0f);
6452                                         light[3] = vec[0];
6453                                 }
6454                                 else if (n == 4)
6455                                 {
6456                                         // halflife
6457                                         light[0] = vec[0] * (1.0f / 255.0f);
6458                                         light[1] = vec[1] * (1.0f / 255.0f);
6459                                         light[2] = vec[2] * (1.0f / 255.0f);
6460                                         light[3] = vec[3];
6461                                 }
6462                         }
6463                         else if (!strcmp("delay", key))
6464                                 type = atoi(value);
6465                         else if (!strcmp("origin", key))
6466                                 sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
6467                         else if (!strcmp("angle", key))
6468                                 angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
6469                         else if (!strcmp("angles", key))
6470                                 sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
6471                         else if (!strcmp("color", key))
6472                                 sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
6473                         else if (!strcmp("wait", key))
6474                                 fadescale = atof(value);
6475                         else if (!strcmp("classname", key))
6476                         {
6477                                 if (!strncmp(value, "light", 5))
6478                                 {
6479                                         islight = true;
6480                                         if (!strcmp(value, "light_fluoro"))
6481                                         {
6482                                                 originhack[0] = 0;
6483                                                 originhack[1] = 0;
6484                                                 originhack[2] = 0;
6485                                                 overridecolor[0] = 1;
6486                                                 overridecolor[1] = 1;
6487                                                 overridecolor[2] = 1;
6488                                         }
6489                                         if (!strcmp(value, "light_fluorospark"))
6490                                         {
6491                                                 originhack[0] = 0;
6492                                                 originhack[1] = 0;
6493                                                 originhack[2] = 0;
6494                                                 overridecolor[0] = 1;
6495                                                 overridecolor[1] = 1;
6496                                                 overridecolor[2] = 1;
6497                                         }
6498                                         if (!strcmp(value, "light_globe"))
6499                                         {
6500                                                 originhack[0] = 0;
6501                                                 originhack[1] = 0;
6502                                                 originhack[2] = 0;
6503                                                 overridecolor[0] = 1;
6504                                                 overridecolor[1] = 0.8;
6505                                                 overridecolor[2] = 0.4;
6506                                         }
6507                                         if (!strcmp(value, "light_flame_large_yellow"))
6508                                         {
6509                                                 originhack[0] = 0;
6510                                                 originhack[1] = 0;
6511                                                 originhack[2] = 0;
6512                                                 overridecolor[0] = 1;
6513                                                 overridecolor[1] = 0.5;
6514                                                 overridecolor[2] = 0.1;
6515                                         }
6516                                         if (!strcmp(value, "light_flame_small_yellow"))
6517                                         {
6518                                                 originhack[0] = 0;
6519                                                 originhack[1] = 0;
6520                                                 originhack[2] = 0;
6521                                                 overridecolor[0] = 1;
6522                                                 overridecolor[1] = 0.5;
6523                                                 overridecolor[2] = 0.1;
6524                                         }
6525                                         if (!strcmp(value, "light_torch_small_white"))
6526                                         {
6527                                                 originhack[0] = 0;
6528                                                 originhack[1] = 0;
6529                                                 originhack[2] = 0;
6530                                                 overridecolor[0] = 1;
6531                                                 overridecolor[1] = 0.5;
6532                                                 overridecolor[2] = 0.1;
6533                                         }
6534                                         if (!strcmp(value, "light_torch_small_walltorch"))
6535                                         {
6536                                                 originhack[0] = 0;
6537                                                 originhack[1] = 0;
6538                                                 originhack[2] = 0;
6539                                                 overridecolor[0] = 1;
6540                                                 overridecolor[1] = 0.5;
6541                                                 overridecolor[2] = 0.1;
6542                                         }
6543                                 }
6544                         }
6545                         else if (!strcmp("style", key))
6546                                 style = atoi(value);
6547                         else if (!strcmp("skin", key))
6548                                 skin = (int)atof(value);
6549                         else if (!strcmp("pflags", key))
6550                                 pflags = (int)atof(value);
6551                         //else if (!strcmp("effects", key))
6552                         //      effects = (int)atof(value);
6553                         else if (cl.worldmodel->type == mod_brushq3)
6554                         {
6555                                 if (!strcmp("scale", key))
6556                                         lightscale = atof(value);
6557                                 if (!strcmp("fade", key))
6558                                         fadescale = atof(value);
6559                         }
6560                 }
6561                 if (!islight)
6562                         continue;
6563                 if (lightscale <= 0)
6564                         lightscale = 1;
6565                 if (fadescale <= 0)
6566                         fadescale = 1;
6567                 if (color[0] == color[1] && color[0] == color[2])
6568                 {
6569                         color[0] *= overridecolor[0];
6570                         color[1] *= overridecolor[1];
6571                         color[2] *= overridecolor[2];
6572                 }
6573                 radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
6574                 color[0] = color[0] * light[0];
6575                 color[1] = color[1] * light[1];
6576                 color[2] = color[2] * light[2];
6577                 switch (type)
6578                 {
6579                 case LIGHTTYPE_MINUSX:
6580                         break;
6581                 case LIGHTTYPE_RECIPX:
6582                         radius *= 2;
6583                         VectorScale(color, (1.0f / 16.0f), color);
6584                         break;
6585                 case LIGHTTYPE_RECIPXX:
6586                         radius *= 2;
6587                         VectorScale(color, (1.0f / 16.0f), color);
6588                         break;
6589                 default:
6590                 case LIGHTTYPE_NONE:
6591                         break;
6592                 case LIGHTTYPE_SUN:
6593                         break;
6594                 case LIGHTTYPE_MINUSXX:
6595                         break;
6596                 }
6597                 VectorAdd(origin, originhack, origin);
6598                 if (radius >= 1)
6599                         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);
6600         }
6601         if (entfiledata)
6602                 Mem_Free(entfiledata);
6603 }
6604
6605
6606 static void R_Shadow_SetCursorLocationForView(void)
6607 {
6608         vec_t dist, push;
6609         vec3_t dest, endpos;
6610         trace_t trace;
6611         VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
6612         trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true);
6613         if (trace.fraction < 1)
6614         {
6615                 dist = trace.fraction * r_editlights_cursordistance.value;
6616                 push = r_editlights_cursorpushback.value;
6617                 if (push > dist)
6618                         push = dist;
6619                 push = -push;
6620                 VectorMA(trace.endpos, push, r_refdef.view.forward, endpos);
6621                 VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
6622         }
6623         else
6624         {
6625                 VectorClear( endpos );
6626         }
6627         r_editlights_cursorlocation[0] = floor(endpos[0] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6628         r_editlights_cursorlocation[1] = floor(endpos[1] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6629         r_editlights_cursorlocation[2] = floor(endpos[2] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
6630 }
6631
6632 void R_Shadow_UpdateWorldLightSelection(void)
6633 {
6634         if (r_editlights.integer)
6635         {
6636                 R_Shadow_SetCursorLocationForView();
6637                 R_Shadow_SelectLightInView();
6638         }
6639         else
6640                 R_Shadow_SelectLight(NULL);
6641 }
6642
6643 static void R_Shadow_EditLights_Clear_f(void)
6644 {
6645         R_Shadow_ClearWorldLights();
6646 }
6647
6648 void R_Shadow_EditLights_Reload_f(void)
6649 {
6650         if (!cl.worldmodel)
6651                 return;
6652         strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname));
6653         R_Shadow_ClearWorldLights();
6654         if (r_shadow_realtime_world_importlightentitiesfrommap.integer <= 1)
6655         {
6656                 R_Shadow_LoadWorldLights();
6657                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6658                         R_Shadow_LoadLightsFile();
6659         }
6660         if (r_shadow_realtime_world_importlightentitiesfrommap.integer >= 1)
6661         {
6662                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
6663                         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6664         }
6665 }
6666
6667 static void R_Shadow_EditLights_Save_f(void)
6668 {
6669         if (!cl.worldmodel)
6670                 return;
6671         R_Shadow_SaveWorldLights();
6672 }
6673
6674 static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
6675 {
6676         R_Shadow_ClearWorldLights();
6677         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
6678 }
6679
6680 static void R_Shadow_EditLights_ImportLightsFile_f(void)
6681 {
6682         R_Shadow_ClearWorldLights();
6683         R_Shadow_LoadLightsFile();
6684 }
6685
6686 static void R_Shadow_EditLights_Spawn_f(void)
6687 {
6688         vec3_t color;
6689         if (!r_editlights.integer)
6690         {
6691                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6692                 return;
6693         }
6694         if (Cmd_Argc() != 1)
6695         {
6696                 Con_Print("r_editlights_spawn does not take parameters\n");
6697                 return;
6698         }
6699         color[0] = color[1] = color[2] = 1;
6700         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
6701 }
6702
6703 static void R_Shadow_EditLights_Edit_f(void)
6704 {
6705         vec3_t origin, angles, color;
6706         vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
6707         int style, shadows, flags, normalmode, realtimemode;
6708         char cubemapname[MAX_INPUTLINE];
6709         if (!r_editlights.integer)
6710         {
6711                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
6712                 return;
6713         }
6714         if (!r_shadow_selectedlight)
6715         {
6716                 Con_Print("No selected light.\n");
6717                 return;
6718         }
6719         VectorCopy(r_shadow_selectedlight->origin, origin);
6720         VectorCopy(r_shadow_selectedlight->angles, angles);
6721         VectorCopy(r_shadow_selectedlight->color, color);
6722         radius = r_shadow_selectedlight->radius;
6723         style = r_shadow_selectedlight->style;
6724         if (r_shadow_selectedlight->cubemapname)
6725                 strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
6726         else
6727                 cubemapname[0] = 0;
6728         shadows = r_shadow_selectedlight->shadow;
6729         corona = r_shadow_selectedlight->corona;
6730         coronasizescale = r_shadow_selectedlight->coronasizescale;
6731         ambientscale = r_shadow_selectedlight->ambientscale;
6732         diffusescale = r_shadow_selectedlight->diffusescale;
6733         specularscale = r_shadow_selectedlight->specularscale;
6734         flags = r_shadow_selectedlight->flags;
6735         normalmode = (flags & LIGHTFLAG_NORMALMODE) != 0;
6736         realtimemode = (flags & LIGHTFLAG_REALTIMEMODE) != 0;
6737         if (!strcmp(Cmd_Argv(1), "origin"))
6738         {
6739                 if (Cmd_Argc() != 5)
6740                 {
6741                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6742                         return;
6743                 }
6744                 origin[0] = atof(Cmd_Argv(2));
6745                 origin[1] = atof(Cmd_Argv(3));
6746                 origin[2] = atof(Cmd_Argv(4));
6747         }
6748         else if (!strcmp(Cmd_Argv(1), "originscale"))
6749         {
6750                 if (Cmd_Argc() != 5)
6751                 {
6752                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6753                         return;
6754                 }
6755                 origin[0] *= atof(Cmd_Argv(2));
6756                 origin[1] *= atof(Cmd_Argv(3));
6757                 origin[2] *= atof(Cmd_Argv(4));
6758         }
6759         else if (!strcmp(Cmd_Argv(1), "originx"))
6760         {
6761                 if (Cmd_Argc() != 3)
6762                 {
6763                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6764                         return;
6765                 }
6766                 origin[0] = atof(Cmd_Argv(2));
6767         }
6768         else if (!strcmp(Cmd_Argv(1), "originy"))
6769         {
6770                 if (Cmd_Argc() != 3)
6771                 {
6772                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6773                         return;
6774                 }
6775                 origin[1] = atof(Cmd_Argv(2));
6776         }
6777         else if (!strcmp(Cmd_Argv(1), "originz"))
6778         {
6779                 if (Cmd_Argc() != 3)
6780                 {
6781                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6782                         return;
6783                 }
6784                 origin[2] = atof(Cmd_Argv(2));
6785         }
6786         else if (!strcmp(Cmd_Argv(1), "move"))
6787         {
6788                 if (Cmd_Argc() != 5)
6789                 {
6790                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6791                         return;
6792                 }
6793                 origin[0] += atof(Cmd_Argv(2));
6794                 origin[1] += atof(Cmd_Argv(3));
6795                 origin[2] += atof(Cmd_Argv(4));
6796         }
6797         else if (!strcmp(Cmd_Argv(1), "movex"))
6798         {
6799                 if (Cmd_Argc() != 3)
6800                 {
6801                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6802                         return;
6803                 }
6804                 origin[0] += atof(Cmd_Argv(2));
6805         }
6806         else if (!strcmp(Cmd_Argv(1), "movey"))
6807         {
6808                 if (Cmd_Argc() != 3)
6809                 {
6810                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6811                         return;
6812                 }
6813                 origin[1] += atof(Cmd_Argv(2));
6814         }
6815         else if (!strcmp(Cmd_Argv(1), "movez"))
6816         {
6817                 if (Cmd_Argc() != 3)
6818                 {
6819                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6820                         return;
6821                 }
6822                 origin[2] += atof(Cmd_Argv(2));
6823         }
6824         else if (!strcmp(Cmd_Argv(1), "angles"))
6825         {
6826                 if (Cmd_Argc() != 5)
6827                 {
6828                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
6829                         return;
6830                 }
6831                 angles[0] = atof(Cmd_Argv(2));
6832                 angles[1] = atof(Cmd_Argv(3));
6833                 angles[2] = atof(Cmd_Argv(4));
6834         }
6835         else if (!strcmp(Cmd_Argv(1), "anglesx"))
6836         {
6837                 if (Cmd_Argc() != 3)
6838                 {
6839                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6840                         return;
6841                 }
6842                 angles[0] = atof(Cmd_Argv(2));
6843         }
6844         else if (!strcmp(Cmd_Argv(1), "anglesy"))
6845         {
6846                 if (Cmd_Argc() != 3)
6847                 {
6848                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6849                         return;
6850                 }
6851                 angles[1] = atof(Cmd_Argv(2));
6852         }
6853         else if (!strcmp(Cmd_Argv(1), "anglesz"))
6854         {
6855                 if (Cmd_Argc() != 3)
6856                 {
6857                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6858                         return;
6859                 }
6860                 angles[2] = atof(Cmd_Argv(2));
6861         }
6862         else if (!strcmp(Cmd_Argv(1), "color"))
6863         {
6864                 if (Cmd_Argc() != 5)
6865                 {
6866                         Con_Printf("usage: r_editlights_edit %s red green blue\n", Cmd_Argv(1));
6867                         return;
6868                 }
6869                 color[0] = atof(Cmd_Argv(2));
6870                 color[1] = atof(Cmd_Argv(3));
6871                 color[2] = atof(Cmd_Argv(4));
6872         }
6873         else if (!strcmp(Cmd_Argv(1), "radius"))
6874         {
6875                 if (Cmd_Argc() != 3)
6876                 {
6877                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6878                         return;
6879                 }
6880                 radius = atof(Cmd_Argv(2));
6881         }
6882         else if (!strcmp(Cmd_Argv(1), "colorscale"))
6883         {
6884                 if (Cmd_Argc() == 3)
6885                 {
6886                         double scale = atof(Cmd_Argv(2));
6887                         color[0] *= scale;
6888                         color[1] *= scale;
6889                         color[2] *= scale;
6890                 }
6891                 else
6892                 {
6893                         if (Cmd_Argc() != 5)
6894                         {
6895                                 Con_Printf("usage: r_editlights_edit %s red green blue  (OR grey instead of red green blue)\n", Cmd_Argv(1));
6896                                 return;
6897                         }
6898                         color[0] *= atof(Cmd_Argv(2));
6899                         color[1] *= atof(Cmd_Argv(3));
6900                         color[2] *= atof(Cmd_Argv(4));
6901                 }
6902         }
6903         else if (!strcmp(Cmd_Argv(1), "radiusscale") || !strcmp(Cmd_Argv(1), "sizescale"))
6904         {
6905                 if (Cmd_Argc() != 3)
6906                 {
6907                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6908                         return;
6909                 }
6910                 radius *= atof(Cmd_Argv(2));
6911         }
6912         else if (!strcmp(Cmd_Argv(1), "style"))
6913         {
6914                 if (Cmd_Argc() != 3)
6915                 {
6916                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6917                         return;
6918                 }
6919                 style = atoi(Cmd_Argv(2));
6920         }
6921         else if (!strcmp(Cmd_Argv(1), "cubemap"))
6922         {
6923                 if (Cmd_Argc() > 3)
6924                 {
6925                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6926                         return;
6927                 }
6928                 if (Cmd_Argc() == 3)
6929                         strlcpy(cubemapname, Cmd_Argv(2), sizeof(cubemapname));
6930                 else
6931                         cubemapname[0] = 0;
6932         }
6933         else if (!strcmp(Cmd_Argv(1), "shadows"))
6934         {
6935                 if (Cmd_Argc() != 3)
6936                 {
6937                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6938                         return;
6939                 }
6940                 shadows = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
6941         }
6942         else if (!strcmp(Cmd_Argv(1), "corona"))
6943         {
6944                 if (Cmd_Argc() != 3)
6945                 {
6946                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6947                         return;
6948                 }
6949                 corona = atof(Cmd_Argv(2));
6950         }
6951         else if (!strcmp(Cmd_Argv(1), "coronasize"))
6952         {
6953                 if (Cmd_Argc() != 3)
6954                 {
6955                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6956                         return;
6957                 }
6958                 coronasizescale = atof(Cmd_Argv(2));
6959         }
6960         else if (!strcmp(Cmd_Argv(1), "ambient"))
6961         {
6962                 if (Cmd_Argc() != 3)
6963                 {
6964                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6965                         return;
6966                 }
6967                 ambientscale = atof(Cmd_Argv(2));
6968         }
6969         else if (!strcmp(Cmd_Argv(1), "diffuse"))
6970         {
6971                 if (Cmd_Argc() != 3)
6972                 {
6973                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6974                         return;
6975                 }
6976                 diffusescale = atof(Cmd_Argv(2));
6977         }
6978         else if (!strcmp(Cmd_Argv(1), "specular"))
6979         {
6980                 if (Cmd_Argc() != 3)
6981                 {
6982                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6983                         return;
6984                 }
6985                 specularscale = atof(Cmd_Argv(2));
6986         }
6987         else if (!strcmp(Cmd_Argv(1), "normalmode"))
6988         {
6989                 if (Cmd_Argc() != 3)
6990                 {
6991                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
6992                         return;
6993                 }
6994                 normalmode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
6995         }
6996         else if (!strcmp(Cmd_Argv(1), "realtimemode"))
6997         {
6998                 if (Cmd_Argc() != 3)
6999                 {
7000                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
7001                         return;
7002                 }
7003                 realtimemode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
7004         }
7005         else
7006         {
7007                 Con_Print("usage: r_editlights_edit [property] [value]\n");
7008                 Con_Print("Selected light's properties:\n");
7009                 Con_Printf("Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
7010                 Con_Printf("Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
7011                 Con_Printf("Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
7012                 Con_Printf("Radius       : %f\n", r_shadow_selectedlight->radius);
7013                 Con_Printf("Corona       : %f\n", r_shadow_selectedlight->corona);
7014                 Con_Printf("Style        : %i\n", r_shadow_selectedlight->style);
7015                 Con_Printf("Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
7016                 Con_Printf("Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);
7017                 Con_Printf("CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);
7018                 Con_Printf("Ambient      : %f\n", r_shadow_selectedlight->ambientscale);
7019                 Con_Printf("Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);
7020                 Con_Printf("Specular     : %f\n", r_shadow_selectedlight->specularscale);
7021                 Con_Printf("NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");
7022                 Con_Printf("RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");
7023                 return;
7024         }
7025         flags = (normalmode ? LIGHTFLAG_NORMALMODE : 0) | (realtimemode ? LIGHTFLAG_REALTIMEMODE : 0);
7026         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
7027 }
7028
7029 static void R_Shadow_EditLights_EditAll_f(void)
7030 {
7031         size_t lightindex;
7032         dlight_t *light, *oldselected;
7033         size_t range;
7034
7035         if (!r_editlights.integer)
7036         {
7037                 Con_Print("Cannot edit lights when not in editing mode. Set r_editlights to 1.\n");
7038                 return;
7039         }
7040
7041         oldselected = r_shadow_selectedlight;
7042         // EditLights doesn't seem to have a "remove" command or something so:
7043         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7044         for (lightindex = 0;lightindex < range;lightindex++)
7045         {
7046                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7047                 if (!light)
7048                         continue;
7049                 R_Shadow_SelectLight(light);
7050                 R_Shadow_EditLights_Edit_f();
7051         }
7052         // return to old selected (to not mess editing once selection is locked)
7053         R_Shadow_SelectLight(oldselected);
7054 }
7055
7056 void R_Shadow_EditLights_DrawSelectedLightProperties(void)
7057 {
7058         int lightnumber, lightcount;
7059         size_t lightindex, range;
7060         dlight_t *light;
7061         char temp[256];
7062         float x, y;
7063
7064         if (!r_editlights.integer)
7065                 return;
7066
7067         // update cvars so QC can query them
7068         if (r_shadow_selectedlight)
7069         {
7070                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
7071                 Cvar_SetQuick(&r_editlights_current_origin, temp);
7072                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
7073                 Cvar_SetQuick(&r_editlights_current_angles, temp);
7074                 dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
7075                 Cvar_SetQuick(&r_editlights_current_color, temp);
7076                 Cvar_SetValueQuick(&r_editlights_current_radius, r_shadow_selectedlight->radius);
7077                 Cvar_SetValueQuick(&r_editlights_current_corona, r_shadow_selectedlight->corona);
7078                 Cvar_SetValueQuick(&r_editlights_current_coronasize, r_shadow_selectedlight->coronasizescale);
7079                 Cvar_SetValueQuick(&r_editlights_current_style, r_shadow_selectedlight->style);
7080                 Cvar_SetValueQuick(&r_editlights_current_shadows, r_shadow_selectedlight->shadow);
7081                 Cvar_SetQuick(&r_editlights_current_cubemap, r_shadow_selectedlight->cubemapname);
7082                 Cvar_SetValueQuick(&r_editlights_current_ambient, r_shadow_selectedlight->ambientscale);
7083                 Cvar_SetValueQuick(&r_editlights_current_diffuse, r_shadow_selectedlight->diffusescale);
7084                 Cvar_SetValueQuick(&r_editlights_current_specular, r_shadow_selectedlight->specularscale);
7085                 Cvar_SetValueQuick(&r_editlights_current_normalmode, (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? 1 : 0);
7086                 Cvar_SetValueQuick(&r_editlights_current_realtimemode, (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? 1 : 0);
7087         }
7088
7089         // draw properties on screen
7090         if (!r_editlights_drawproperties.integer)
7091                 return;
7092         x = vid_conwidth.value - 240;
7093         y = 5;
7094         DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
7095         lightnumber = -1;
7096         lightcount = 0;
7097         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
7098         for (lightindex = 0;lightindex < range;lightindex++)
7099         {
7100                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
7101                 if (!light)
7102                         continue;
7103                 if (light == r_shadow_selectedlight)
7104                         lightnumber = (int)lightindex;
7105                 lightcount++;
7106         }
7107         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;
7108         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;
7109         y += 8;
7110         if (r_shadow_selectedlight == NULL)
7111                 return;
7112         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;
7113         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;
7114         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;
7115         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;
7116         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;
7117         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;
7118         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;
7119         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;
7120         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;
7121         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;
7122         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;
7123         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;
7124         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;
7125         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;
7126         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;
7127 }
7128
7129 static void R_Shadow_EditLights_ToggleShadow_f(void)
7130 {
7131         if (!r_editlights.integer)
7132         {
7133                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7134                 return;
7135         }
7136         if (!r_shadow_selectedlight)
7137         {
7138                 Con_Print("No selected light.\n");
7139                 return;
7140         }
7141         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);
7142 }
7143
7144 static void R_Shadow_EditLights_ToggleCorona_f(void)
7145 {
7146         if (!r_editlights.integer)
7147         {
7148                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
7149                 return;
7150         }
7151         if (!r_shadow_selectedlight)
7152         {
7153                 Con_Print("No selected light.\n");
7154                 return;
7155         }
7156         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);
7157 }
7158
7159 static void R_Shadow_EditLights_Remove_f(void)
7160 {
7161         if (!r_editlights.integer)
7162         {
7163                 Con_Print("Cannot remove light when not in editing mode.  Set r_editlights to 1.\n");
7164                 return;
7165         }
7166         if (!r_shadow_selectedlight)
7167         {
7168                 Con_Print("No selected light.\n");
7169                 return;
7170         }
7171         R_Shadow_FreeWorldLight(r_shadow_selectedlight);
7172         r_shadow_selectedlight = NULL;
7173 }
7174
7175 static void R_Shadow_EditLights_Help_f(void)
7176 {
7177         Con_Print(
7178 "Documentation on r_editlights system:\n"
7179 "Settings:\n"
7180 "r_editlights : enable/disable editing mode\n"
7181 "r_editlights_cursordistance : maximum distance of cursor from eye\n"
7182 "r_editlights_cursorpushback : push back cursor this far from surface\n"
7183 "r_editlights_cursorpushoff : push cursor off surface this far\n"
7184 "r_editlights_cursorgrid : snap cursor to grid of this size\n"
7185 "r_editlights_quakelightsizescale : imported quake light entity size scaling\n"
7186 "Commands:\n"
7187 "r_editlights_help : this help\n"
7188 "r_editlights_clear : remove all lights\n"
7189 "r_editlights_reload : reload .rtlights, .lights file, or entities\n"
7190 "r_editlights_lock : lock selection to current light, if already locked - unlock\n"
7191 "r_editlights_save : save to .rtlights file\n"
7192 "r_editlights_spawn : create a light with default settings\n"
7193 "r_editlights_edit command : edit selected light - more documentation below\n"
7194 "r_editlights_remove : remove selected light\n"
7195 "r_editlights_toggleshadow : toggles on/off selected light's shadow property\n"
7196 "r_editlights_importlightentitiesfrommap : reload light entities\n"
7197 "r_editlights_importlightsfile : reload .light file (produced by hlight)\n"
7198 "Edit commands:\n"
7199 "origin x y z : set light location\n"
7200 "originx x: set x component of light location\n"
7201 "originy y: set y component of light location\n"
7202 "originz z: set z component of light location\n"
7203 "move x y z : adjust light location\n"
7204 "movex x: adjust x component of light location\n"
7205 "movey y: adjust y component of light location\n"
7206 "movez z: adjust z component of light location\n"
7207 "angles x y z : set light angles\n"
7208 "anglesx x: set x component of light angles\n"
7209 "anglesy y: set y component of light angles\n"
7210 "anglesz z: set z component of light angles\n"
7211 "color r g b : set color of light (can be brighter than 1 1 1)\n"
7212 "radius radius : set radius (size) of light\n"
7213 "colorscale grey : multiply color of light (1 does nothing)\n"
7214 "colorscale r g b : multiply color of light (1 1 1 does nothing)\n"
7215 "radiusscale scale : multiply radius (size) of light (1 does nothing)\n"
7216 "sizescale scale : multiply radius (size) of light (1 does nothing)\n"
7217 "originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
7218 "style style : set lightstyle of light (flickering patterns, switches, etc)\n"
7219 "cubemap basename : set filter cubemap of light\n"
7220 "shadows 1/0 : turn on/off shadows\n"
7221 "corona n : set corona intensity\n"
7222 "coronasize n : set corona size (0-1)\n"
7223 "ambient n : set ambient intensity (0-1)\n"
7224 "diffuse n : set diffuse intensity (0-1)\n"
7225 "specular n : set specular intensity (0-1)\n"
7226 "normalmode 1/0 : turn on/off rendering of this light in rtworld 0 mode\n"
7227 "realtimemode 1/0 : turn on/off rendering of this light in rtworld 1 mode\n"
7228 "<nothing> : print light properties to console\n"
7229         );
7230 }
7231
7232 static void R_Shadow_EditLights_CopyInfo_f(void)
7233 {
7234         if (!r_editlights.integer)
7235         {
7236                 Con_Print("Cannot copy light info when not in editing mode.  Set r_editlights to 1.\n");
7237                 return;
7238         }
7239         if (!r_shadow_selectedlight)
7240         {
7241                 Con_Print("No selected light.\n");
7242                 return;
7243         }
7244         VectorCopy(r_shadow_selectedlight->angles, r_shadow_bufferlight.angles);
7245         VectorCopy(r_shadow_selectedlight->color, r_shadow_bufferlight.color);
7246         r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
7247         r_shadow_bufferlight.style = r_shadow_selectedlight->style;
7248         if (r_shadow_selectedlight->cubemapname)
7249                 strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
7250         else
7251                 r_shadow_bufferlight.cubemapname[0] = 0;
7252         r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;
7253         r_shadow_bufferlight.corona = r_shadow_selectedlight->corona;
7254         r_shadow_bufferlight.coronasizescale = r_shadow_selectedlight->coronasizescale;
7255         r_shadow_bufferlight.ambientscale = r_shadow_selectedlight->ambientscale;
7256         r_shadow_bufferlight.diffusescale = r_shadow_selectedlight->diffusescale;
7257         r_shadow_bufferlight.specularscale = r_shadow_selectedlight->specularscale;
7258         r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
7259 }
7260
7261 static void R_Shadow_EditLights_PasteInfo_f(void)
7262 {
7263         if (!r_editlights.integer)
7264         {
7265                 Con_Print("Cannot paste light info when not in editing mode.  Set r_editlights to 1.\n");
7266                 return;
7267         }
7268         if (!r_shadow_selectedlight)
7269         {
7270                 Con_Print("No selected light.\n");
7271                 return;
7272         }
7273         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);
7274 }
7275
7276 static void R_Shadow_EditLights_Lock_f(void)
7277 {
7278         if (!r_editlights.integer)
7279         {
7280                 Con_Print("Cannot lock on light when not in editing mode.  Set r_editlights to 1.\n");
7281                 return;
7282         }
7283         if (r_editlights_lockcursor)
7284         {
7285                 r_editlights_lockcursor = false;
7286                 return;
7287         }
7288         if (!r_shadow_selectedlight)
7289         {
7290                 Con_Print("No selected light to lock on.\n");
7291                 return;
7292         }
7293         r_editlights_lockcursor = true;
7294 }
7295
7296 static void R_Shadow_EditLights_Init(void)
7297 {
7298         Cvar_RegisterVariable(&r_editlights);
7299         Cvar_RegisterVariable(&r_editlights_cursordistance);
7300         Cvar_RegisterVariable(&r_editlights_cursorpushback);
7301         Cvar_RegisterVariable(&r_editlights_cursorpushoff);
7302         Cvar_RegisterVariable(&r_editlights_cursorgrid);
7303         Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
7304         Cvar_RegisterVariable(&r_editlights_drawproperties);
7305         Cvar_RegisterVariable(&r_editlights_current_origin);
7306         Cvar_RegisterVariable(&r_editlights_current_angles);
7307         Cvar_RegisterVariable(&r_editlights_current_color);
7308         Cvar_RegisterVariable(&r_editlights_current_radius);
7309         Cvar_RegisterVariable(&r_editlights_current_corona);
7310         Cvar_RegisterVariable(&r_editlights_current_coronasize);
7311         Cvar_RegisterVariable(&r_editlights_current_style);
7312         Cvar_RegisterVariable(&r_editlights_current_shadows);
7313         Cvar_RegisterVariable(&r_editlights_current_cubemap);
7314         Cvar_RegisterVariable(&r_editlights_current_ambient);
7315         Cvar_RegisterVariable(&r_editlights_current_diffuse);
7316         Cvar_RegisterVariable(&r_editlights_current_specular);
7317         Cvar_RegisterVariable(&r_editlights_current_normalmode);
7318         Cvar_RegisterVariable(&r_editlights_current_realtimemode);
7319         Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
7320         Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
7321         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)");
7322         Cmd_AddCommand("r_editlights_save", R_Shadow_EditLights_Save_f, "save .rtlights file for current level");
7323         Cmd_AddCommand("r_editlights_spawn", R_Shadow_EditLights_Spawn_f, "creates a light with default properties (let there be light!)");
7324         Cmd_AddCommand("r_editlights_edit", R_Shadow_EditLights_Edit_f, "changes a property on the selected light");
7325         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)");
7326         Cmd_AddCommand("r_editlights_remove", R_Shadow_EditLights_Remove_f, "remove selected light");
7327         Cmd_AddCommand("r_editlights_toggleshadow", R_Shadow_EditLights_ToggleShadow_f, "toggle on/off the shadow option on the selected light");
7328         Cmd_AddCommand("r_editlights_togglecorona", R_Shadow_EditLights_ToggleCorona_f, "toggle on/off the corona option on the selected light");
7329         Cmd_AddCommand("r_editlights_importlightentitiesfrommap", R_Shadow_EditLights_ImportLightEntitiesFromMap_f, "load lights from .ent file or map entities (ignoring .rtlights or .lights file)");
7330         Cmd_AddCommand("r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)");
7331         Cmd_AddCommand("r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
7332         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)");
7333         Cmd_AddCommand("r_editlights_lock", R_Shadow_EditLights_Lock_f, "lock selection to current light, if already locked - unlock");
7334 }
7335
7336
7337
7338 /*
7339 =============================================================================
7340
7341 LIGHT SAMPLING
7342
7343 =============================================================================
7344 */
7345
7346 void R_LightPoint(float *color, const vec3_t p, const int flags)
7347 {
7348         int i, numlights, flag;
7349         float f, relativepoint[3], dist, dist2, lightradius2;
7350         vec3_t diffuse, n;
7351         rtlight_t *light;
7352         dlight_t *dlight;
7353
7354         if (r_fullbright.integer)
7355         {
7356                 VectorSet(color, 1, 1, 1);
7357                 return;
7358         }
7359
7360         VectorClear(color);
7361
7362         if (flags & LP_LIGHTMAP)
7363         {
7364                 if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7365                 {
7366                         VectorClear(diffuse);
7367                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, color, diffuse, n);
7368                         VectorAdd(color, diffuse, color);
7369                 }
7370                 else
7371                         VectorSet(color, 1, 1, 1);
7372                 color[0] += r_refdef.scene.ambient;
7373                 color[1] += r_refdef.scene.ambient;
7374                 color[2] += r_refdef.scene.ambient;
7375         }
7376
7377         if (flags & LP_RTWORLD)
7378         {
7379                 flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
7380                 numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
7381                 for (i = 0; i < numlights; i++)
7382                 {
7383                         dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
7384                         if (!dlight)
7385                                 continue;
7386                         light = &dlight->rtlight;
7387                         if (!(light->flags & flag))
7388                                 continue;
7389                         // sample
7390                         lightradius2 = light->radius * light->radius;
7391                         VectorSubtract(light->shadoworigin, p, relativepoint);
7392                         dist2 = VectorLength2(relativepoint);
7393                         if (dist2 >= lightradius2)
7394                                 continue;
7395                         dist = sqrt(dist2) / light->radius;
7396                         f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
7397                         if (f <= 0)
7398                                 continue;
7399                         // todo: add to both ambient and diffuse
7400                         if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
7401                                 VectorMA(color, f, light->currentcolor, color);
7402                 }
7403         }
7404         if (flags & LP_DYNLIGHT)
7405         {
7406                 // sample dlights
7407                 for (i = 0;i < r_refdef.scene.numlights;i++)
7408                 {
7409                         light = r_refdef.scene.lights[i];
7410                         // sample
7411                         lightradius2 = light->radius * light->radius;
7412                         VectorSubtract(light->shadoworigin, p, relativepoint);
7413                         dist2 = VectorLength2(relativepoint);
7414                         if (dist2 >= lightradius2)
7415                                 continue;
7416                         dist = sqrt(dist2) / light->radius;
7417                         f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
7418                         if (f <= 0)
7419                                 continue;
7420                         // todo: add to both ambient and diffuse
7421                         if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
7422                                 VectorMA(color, f, light->color, color);
7423                 }
7424         }
7425 }
7426
7427 void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const vec3_t p, const int flags)
7428 {
7429         int i, numlights, flag;
7430         rtlight_t *light;
7431         dlight_t *dlight;
7432         float relativepoint[3];
7433         float color[3];
7434         float dir[3];
7435         float dist;
7436         float dist2;
7437         float intensity;
7438         float sample[5*3];
7439         float lightradius2;
7440
7441         if (r_fullbright.integer)
7442         {
7443                 VectorSet(ambient, 1, 1, 1);
7444                 VectorClear(diffuse);
7445                 VectorClear(lightdir);
7446                 return;
7447         }
7448
7449         if (flags == LP_LIGHTMAP)
7450         {
7451                 VectorSet(ambient, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
7452                 VectorClear(diffuse);
7453                 VectorClear(lightdir);
7454                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7455                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambient, diffuse, lightdir);
7456                 else
7457                         VectorSet(ambient, 1, 1, 1);
7458                 return;
7459         }
7460
7461         memset(sample, 0, sizeof(sample));
7462         VectorSet(sample, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient);
7463
7464         if ((flags & LP_LIGHTMAP) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
7465         {
7466                 vec3_t tempambient;
7467                 VectorClear(tempambient);
7468                 VectorClear(color);
7469                 VectorClear(relativepoint);
7470                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
7471                 VectorScale(tempambient, r_refdef.lightmapintensity, tempambient);
7472                 VectorScale(color, r_refdef.lightmapintensity, color);
7473                 VectorAdd(sample, tempambient, sample);
7474                 VectorMA(sample    , 0.5f            , color, sample    );
7475                 VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7476                 VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7477                 VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7478                 // calculate a weighted average light direction as well
7479                 intensity = VectorLength(color);
7480                 VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7481         }
7482
7483         if (flags & LP_RTWORLD)
7484         {
7485                 flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
7486                 numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
7487                 for (i = 0; i < numlights; i++)
7488                 {
7489                         dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
7490                         if (!dlight)
7491                                 continue;
7492                         light = &dlight->rtlight;
7493                         if (!(light->flags & flag))
7494                                 continue;
7495                         // sample
7496                         lightradius2 = light->radius * light->radius;
7497                         VectorSubtract(light->shadoworigin, p, relativepoint);
7498                         dist2 = VectorLength2(relativepoint);
7499                         if (dist2 >= lightradius2)
7500                                 continue;
7501                         dist = sqrt(dist2) / light->radius;
7502                         intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
7503                         if (intensity <= 0.0f)
7504                                 continue;
7505                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7506                                 continue;
7507                         // scale down intensity to add to both ambient and diffuse
7508                         //intensity *= 0.5f;
7509                         VectorNormalize(relativepoint);
7510                         VectorScale(light->currentcolor, intensity, color);
7511                         VectorMA(sample    , 0.5f            , color, sample    );
7512                         VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7513                         VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7514                         VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7515                         // calculate a weighted average light direction as well
7516                         intensity *= VectorLength(color);
7517                         VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7518                 }
7519                 // FIXME: sample bouncegrid too!
7520         }
7521
7522         if (flags & LP_DYNLIGHT)
7523         {
7524                 // sample dlights
7525                 for (i = 0;i < r_refdef.scene.numlights;i++)
7526                 {
7527                         light = r_refdef.scene.lights[i];
7528                         // sample
7529                         lightradius2 = light->radius * light->radius;
7530                         VectorSubtract(light->shadoworigin, p, relativepoint);
7531                         dist2 = VectorLength2(relativepoint);
7532                         if (dist2 >= lightradius2)
7533                                 continue;
7534                         dist = sqrt(dist2) / light->radius;
7535                         intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
7536                         if (intensity <= 0.0f)
7537                                 continue;
7538                         if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
7539                                 continue;
7540                         // scale down intensity to add to both ambient and diffuse
7541                         //intensity *= 0.5f;
7542                         VectorNormalize(relativepoint);
7543                         VectorScale(light->currentcolor, intensity, color);
7544                         VectorMA(sample    , 0.5f            , color, sample    );
7545                         VectorMA(sample + 3, relativepoint[0], color, sample + 3);
7546                         VectorMA(sample + 6, relativepoint[1], color, sample + 6);
7547                         VectorMA(sample + 9, relativepoint[2], color, sample + 9);
7548                         // calculate a weighted average light direction as well
7549                         intensity *= VectorLength(color);
7550                         VectorMA(sample + 12, intensity, relativepoint, sample + 12);
7551                 }
7552         }
7553
7554         // calculate the direction we'll use to reduce the sample to a directional light source
7555         VectorCopy(sample + 12, dir);
7556         //VectorSet(dir, sample[3] + sample[4] + sample[5], sample[6] + sample[7] + sample[8], sample[9] + sample[10] + sample[11]);
7557         VectorNormalize(dir);
7558         // extract the diffuse color along the chosen direction and scale it
7559         diffuse[0] = (dir[0]*sample[3] + dir[1]*sample[6] + dir[2]*sample[ 9] + sample[ 0]);
7560         diffuse[1] = (dir[0]*sample[4] + dir[1]*sample[7] + dir[2]*sample[10] + sample[ 1]);
7561         diffuse[2] = (dir[0]*sample[5] + dir[1]*sample[8] + dir[2]*sample[11] + sample[ 2]);
7562         // subtract some of diffuse from ambient
7563         VectorMA(sample, -0.333f, diffuse, ambient);
7564         // store the normalized lightdir
7565         VectorCopy(dir, lightdir);
7566 }