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