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