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