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