020a35b4ac40496568a2ba1aa1e5c4f3d9960c89
[xonotic/darkplaces.git] / r_shadow.c
1
2 /*
3 Terminology: Stencil Shadow Volume (sometimes called Stencil Shadows)
4 An extrusion of the lit faces, beginning at the original geometry and ending
5 further from the light source than the original geometry (presumably at least
6 as far as the light's radius, if the light has a radius at all), capped at
7 both front and back to avoid any problems (extrusion from dark faces also
8 works but has a different set of problems)
9
10 This is normally rendered using Carmack's Reverse technique, in which
11 backfaces behind zbuffer (zfail) increment the stencil, and frontfaces behind
12 zbuffer (zfail) decrement the stencil, the result is a stencil value of zero
13 where shadows did not intersect the visible geometry, suitable as a stencil
14 mask for rendering lighting everywhere but shadow.
15
16 In our case to hopefully avoid the Creative Labs patent, we draw the backfaces
17 as decrement and the frontfaces as increment, and we redefine the DepthFunc to
18 GL_LESS (the patent uses GL_GEQUAL) which causes zfail when behind surfaces
19 and zpass when infront (the patent draws where zpass with a GL_GEQUAL test),
20 additionally we clear stencil to 128 to avoid the need for the unclamped
21 incr/decr extension (not related to patent).
22
23 Patent warning:
24 This algorithm may be covered by Creative's patent (US Patent #6384822),
25 however that patent is quite specific about increment on backfaces and
26 decrement on frontfaces where zpass with GL_GEQUAL depth test, which is
27 opposite this implementation and partially opposite Carmack's Reverse paper
28 (which uses GL_LESS, but increments on backfaces and decrements on frontfaces).
29
30
31
32 Terminology: Stencil Light Volume (sometimes called Light Volumes)
33 Similar to a Stencil Shadow Volume, but inverted; rather than containing the
34 areas in shadow it contains the areas in light, this can only be built
35 quickly for certain limited cases (such as portal visibility from a point),
36 but is quite useful for some effects (sunlight coming from sky polygons is
37 one possible example, translucent occluders is another example).
38
39
40
41 Terminology: Optimized Stencil Shadow Volume
42 A Stencil Shadow Volume that has been processed sufficiently to ensure it has
43 no duplicate coverage of areas (no need to shadow an area twice), often this
44 greatly improves performance but is an operation too costly to use on moving
45 lights (however completely optimal Stencil Light Volumes can be constructed
46 in some ideal cases).
47
48
49
50 Terminology: Per Pixel Lighting (sometimes abbreviated PPL)
51 Per pixel evaluation of lighting equations, at a bare minimum this involves
52 DOT3 shading of diffuse lighting (per pixel dotproduct of negated incidence
53 vector and surface normal, using a texture of the surface bumps, called a
54 NormalMap) if supported by hardware; in our case there is support for cards
55 which are incapable of DOT3, the quality is quite poor however.  Additionally
56 it is desirable to have specular evaluation per pixel, per vertex
57 normalization of specular halfangle vectors causes noticable distortion but
58 is unavoidable on hardware without GL_ARB_fragment_program or
59 GL_ARB_fragment_shader.
60
61
62
63 Terminology: Normalization CubeMap
64 A cubemap containing normalized dot3-encoded (vectors of length 1 or less
65 encoded as RGB colors) for any possible direction, this technique allows per
66 pixel calculation of incidence vector for per pixel lighting purposes, which
67 would not otherwise be possible per pixel without GL_ARB_fragment_program or
68 GL_ARB_fragment_shader.
69
70
71
72 Terminology: 2D+1D Attenuation Texturing
73 A very crude approximation of light attenuation with distance which results
74 in cylindrical light shapes which fade vertically as a streak (some games
75 such as Doom3 allow this to be rotated to be less noticable in specific
76 cases), the technique is simply modulating lighting by two 2D textures (which
77 can be the same) on different axes of projection (XY and Z, typically), this
78 is the second best technique available without 3D Attenuation Texturing,
79 GL_ARB_fragment_program or GL_ARB_fragment_shader technology.
80
81
82
83 Terminology: 2D+1D Inverse Attenuation Texturing
84 A clever method described in papers on the Abducted engine, this has a squared
85 distance texture (bright on the outside, black in the middle), which is used
86 twice using GL_ADD blending, the result of this is used in an inverse modulate
87 (GL_ONE_MINUS_DST_ALPHA, GL_ZERO) to implement the equation
88 lighting*=(1-((X*X+Y*Y)+(Z*Z))) which is spherical (unlike 2D+1D attenuation
89 texturing).
90
91
92
93 Terminology: 3D Attenuation Texturing
94 A slightly crude approximation of light attenuation with distance, its flaws
95 are limited radius and resolution (performance tradeoffs).
96
97
98
99 Terminology: 3D Attenuation-Normalization Texturing
100 A 3D Attenuation Texture merged with a Normalization CubeMap, by making the
101 vectors shorter the lighting becomes darker, a very effective optimization of
102 diffuse lighting if 3D Attenuation Textures are already used.
103
104
105
106 Terminology: Light Cubemap Filtering
107 A technique for modeling non-uniform light distribution according to
108 direction, for example a lantern may use a cubemap to describe the light
109 emission pattern of the cage around the lantern (as well as soot buildup
110 discoloring the light in certain areas), often also used for softened grate
111 shadows and light shining through a stained glass window (done crudely by
112 texturing the lighting with a cubemap), another good example would be a disco
113 light.  This technique is used heavily in many games (Doom3 does not support
114 this however).
115
116
117
118 Terminology: Light Projection Filtering
119 A technique for modeling shadowing of light passing through translucent
120 surfaces, allowing stained glass windows and other effects to be done more
121 elegantly than possible with Light Cubemap Filtering by applying an occluder
122 texture to the lighting combined with a stencil light volume to limit the lit
123 area, this technique is used by Doom3 for spotlights and flashlights, among
124 other things, this can also be used more generally to render light passing
125 through multiple translucent occluders in a scene (using a light volume to
126 describe the area beyond the occluder, and thus mask off rendering of all
127 other areas).
128
129
130
131 Terminology: Doom3 Lighting
132 A combination of Stencil Shadow Volume, Per Pixel Lighting, Normalization
133 CubeMap, 2D+1D Attenuation Texturing, and Light Projection Filtering, as
134 demonstrated by the game Doom3.
135 */
136
137 #include "quakedef.h"
138 #include "r_shadow.h"
139 #include "cl_collision.h"
140 #include "portals.h"
141 #include "image.h"
142 #include "dpsoftrast.h"
143
144 #ifdef SUPPORTD3D
145 #include <d3d9.h>
146 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
147 #endif
148
149 extern void R_Shadow_EditLights_Init(void);
150
151 typedef enum r_shadow_rendermode_e
152 {
153         R_SHADOW_RENDERMODE_NONE,
154         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
155         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
156         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
157         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
158         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
159         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
160         R_SHADOW_RENDERMODE_LIGHT_VERTEX,
161         R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN,
162         R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN,
163         R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN,
164         R_SHADOW_RENDERMODE_LIGHT_GLSL,
165         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
166         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
167         R_SHADOW_RENDERMODE_SHADOWMAP2D
168 }
169 r_shadow_rendermode_t;
170
171 typedef enum r_shadow_shadowmode_e
172 {
173     R_SHADOW_SHADOWMODE_STENCIL,
174     R_SHADOW_SHADOWMODE_SHADOWMAP2D
175 }
176 r_shadow_shadowmode_t;
177
178 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
179 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
180 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
181 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
182 qboolean r_shadow_usingshadowmap2d;
183 qboolean r_shadow_usingshadowmaportho;
184 int r_shadow_shadowmapside;
185 float r_shadow_shadowmap_texturescale[2];
186 float r_shadow_shadowmap_parameters[4];
187 #if 0
188 int r_shadow_drawbuffer;
189 int r_shadow_readbuffer;
190 #endif
191 int r_shadow_cullface_front, r_shadow_cullface_back;
192 GLuint r_shadow_fbo2d;
193 r_shadow_shadowmode_t r_shadow_shadowmode;
194 int r_shadow_shadowmapfilterquality;
195 int r_shadow_shadowmapdepthbits;
196 int r_shadow_shadowmapmaxsize;
197 qboolean r_shadow_shadowmapvsdct;
198 qboolean r_shadow_shadowmapsampler;
199 int r_shadow_shadowmappcf;
200 int r_shadow_shadowmapborder;
201 matrix4x4_t r_shadow_shadowmapmatrix;
202 int r_shadow_lightscissor[4];
203 qboolean r_shadow_usingdeferredprepass;
204
205 int maxshadowtriangles;
206 int *shadowelements;
207
208 int maxshadowvertices;
209 float *shadowvertex3f;
210
211 int maxshadowmark;
212 int numshadowmark;
213 int *shadowmark;
214 int *shadowmarklist;
215 int shadowmarkcount;
216
217 int maxshadowsides;
218 int numshadowsides;
219 unsigned char *shadowsides;
220 int *shadowsideslist;
221
222 int maxvertexupdate;
223 int *vertexupdate;
224 int *vertexremap;
225 int vertexupdatenum;
226
227 int r_shadow_buffer_numleafpvsbytes;
228 unsigned char *r_shadow_buffer_visitingleafpvs;
229 unsigned char *r_shadow_buffer_leafpvs;
230 int *r_shadow_buffer_leaflist;
231
232 int r_shadow_buffer_numsurfacepvsbytes;
233 unsigned char *r_shadow_buffer_surfacepvs;
234 int *r_shadow_buffer_surfacelist;
235 unsigned char *r_shadow_buffer_surfacesides;
236
237 int r_shadow_buffer_numshadowtrispvsbytes;
238 unsigned char *r_shadow_buffer_shadowtrispvs;
239 int r_shadow_buffer_numlighttrispvsbytes;
240 unsigned char *r_shadow_buffer_lighttrispvs;
241
242 rtexturepool_t *r_shadow_texturepool;
243 rtexture_t *r_shadow_attenuationgradienttexture;
244 rtexture_t *r_shadow_attenuation2dtexture;
245 rtexture_t *r_shadow_attenuation3dtexture;
246 skinframe_t *r_shadow_lightcorona;
247 rtexture_t *r_shadow_shadowmap2dtexture;
248 rtexture_t *r_shadow_shadowmap2dcolortexture;
249 rtexture_t *r_shadow_shadowmapvsdcttexture;
250 int r_shadow_shadowmapsize; // changes for each light based on distance
251 int r_shadow_shadowmaplod; // changes for each light based on distance
252
253 GLuint r_shadow_prepassgeometryfbo;
254 GLuint r_shadow_prepasslightingdiffusespecularfbo;
255 GLuint r_shadow_prepasslightingdiffusefbo;
256 int r_shadow_prepass_width;
257 int r_shadow_prepass_height;
258 rtexture_t *r_shadow_prepassgeometrydepthtexture;
259 rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
260 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
261 rtexture_t *r_shadow_prepasslightingdiffusetexture;
262 rtexture_t *r_shadow_prepasslightingspeculartexture;
263
264 // 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 #ifndef USE_GLES2
276 static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
277 #endif
278
279 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"};
280 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"};
281 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
282 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"};
283 cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "4", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
284 //cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
285 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)"};
286 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
287 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)"};
288 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"};
289 cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
290 cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
291 cvar_t r_shadow_gloss2exponent = {0, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
292 cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
293 cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
294 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
295 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
296 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
297 cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
298 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)"};
299 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
300 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
301 cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
302 cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
303 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)"};
304 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"};
305 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
306 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
307 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"};
308 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)"};
309 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
310 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)"};
311 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"};
312 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)"};
313 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
314 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
315 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
316 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
317 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"};
318 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
319 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
320 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
321 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
322 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
323 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
324 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
325 cvar_t r_shadow_sortsurfaces = {0, "r_shadow_sortsurfaces", "1", "improve performance by sorting illuminated surfaces by texture"};
326 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
327 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)"};
328 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)"};
329 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)"};
330 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"};
331 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"};
332 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"};
333 cvar_t r_shadow_bouncegrid_hitmodels = {CVAR_SAVE, "r_shadow_bouncegrid_hitmodels", "0", "enables hitting character model geometry (SLOW)"};
334 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)"};
335 cvar_t r_shadow_bouncegrid_intensity = {CVAR_SAVE, "r_shadow_bouncegrid_intensity", "4", "overall brightness of bouncegrid texture"};
336 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)"};
337 cvar_t r_shadow_bouncegrid_maxbounce = {CVAR_SAVE, "r_shadow_bouncegrid_maxbounce", "2", "maximum number of bounces for a particle (minimum is 0)"};
338 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"};
339 cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "1", "brightness of particles contributing to bouncegrid texture"};
340 cvar_t r_shadow_bouncegrid_photons = {CVAR_SAVE, "r_shadow_bouncegrid_photons", "2000", "total photons to shoot per update, divided proportionately between lights"};
341 cvar_t r_shadow_bouncegrid_spacing = {CVAR_SAVE, "r_shadow_bouncegrid_spacing", "64", "unit size of bouncegrid pixel"};
342 cvar_t r_shadow_bouncegrid_stablerandom = {CVAR_SAVE, "r_shadow_bouncegrid_stablerandom", "1", "make particle distribution consistent from frame to frame"};
343 cvar_t r_shadow_bouncegrid_static = {CVAR_SAVE, "r_shadow_bouncegrid_static", "1", "use static radiosity solution (high quality) rather than dynamic (splotchy)"};
344 cvar_t r_shadow_bouncegrid_static_directionalshading = {CVAR_SAVE, "r_shadow_bouncegrid_static_directionalshading", "1", "whether to use directionalshading when in static mode"};
345 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"};
346 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"};
347 cvar_t r_shadow_bouncegrid_static_photons = {CVAR_SAVE, "r_shadow_bouncegrid_static_photons", "25000", "photons value to use when in static mode"};
348 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"};
349 cvar_t r_shadow_bouncegrid_x = {CVAR_SAVE, "r_shadow_bouncegrid_x", "64", "maximum texture size of bouncegrid on X axis"};
350 cvar_t r_shadow_bouncegrid_y = {CVAR_SAVE, "r_shadow_bouncegrid_y", "64", "maximum texture size of bouncegrid on Y axis"};
351 cvar_t r_shadow_bouncegrid_z = {CVAR_SAVE, "r_shadow_bouncegrid_z", "32", "maximum texture size of bouncegrid on Z axis"};
352 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
353 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"};
354 cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
355 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
356 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
357 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
358 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
359 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
360 cvar_t r_editlights_cursorpushback = {0, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
361 cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
362 cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
363 cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
364
365 typedef struct r_shadow_bouncegrid_settings_s
366 {
367         qboolean staticmode;
368         qboolean bounceanglediffuse;
369         qboolean directionalshading;
370         qboolean includedirectlighting;
371         float dlightparticlemultiplier;
372         qboolean hitmodels;
373         float lightradiusscale;
374         int maxbounce;
375         float particlebounceintensity;
376         float particleintensity;
377         int photons;
378         float spacing[3];
379         int stablerandom;
380 }
381 r_shadow_bouncegrid_settings_t;
382
383 r_shadow_bouncegrid_settings_t r_shadow_bouncegridsettings;
384 rtexture_t *r_shadow_bouncegridtexture;
385 matrix4x4_t r_shadow_bouncegridmatrix;
386 vec_t r_shadow_bouncegridintensity;
387 qboolean r_shadow_bouncegriddirectional;
388 static double r_shadow_bouncegridtime;
389 static int r_shadow_bouncegridresolution[3];
390 static int r_shadow_bouncegridnumpixels;
391 static unsigned char *r_shadow_bouncegridpixels;
392 static float *r_shadow_bouncegridhighpixels;
393
394 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
395 #define ATTENTABLESIZE 256
396 // 1D gradient, 2D circle and 3D sphere attenuation textures
397 #define ATTEN1DSIZE 32
398 #define ATTEN2DSIZE 64
399 #define ATTEN3DSIZE 32
400
401 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
402 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
403 static float r_shadow_attentable[ATTENTABLESIZE+1];
404
405 rtlight_t *r_shadow_compilingrtlight;
406 static memexpandablearray_t r_shadow_worldlightsarray;
407 dlight_t *r_shadow_selectedlight;
408 dlight_t r_shadow_bufferlight;
409 vec3_t r_editlights_cursorlocation;
410 qboolean r_editlights_lockcursor;
411
412 extern int con_vislines;
413
414 void R_Shadow_UncompileWorldLights(void);
415 void R_Shadow_ClearWorldLights(void);
416 void R_Shadow_SaveWorldLights(void);
417 void R_Shadow_LoadWorldLights(void);
418 void R_Shadow_LoadLightsFile(void);
419 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
420 void R_Shadow_EditLights_Reload_f(void);
421 void R_Shadow_ValidateCvars(void);
422 static void R_Shadow_MakeTextures(void);
423
424 #define EDLIGHTSPRSIZE                  8
425 skinframe_t *r_editlights_sprcursor;
426 skinframe_t *r_editlights_sprlight;
427 skinframe_t *r_editlights_sprnoshadowlight;
428 skinframe_t *r_editlights_sprcubemaplight;
429 skinframe_t *r_editlights_sprcubemapnoshadowlight;
430 skinframe_t *r_editlights_sprselection;
431
432 void R_Shadow_SetShadowMode(void)
433 {
434         r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
435         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20;
436         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
437         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
438         r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
439         r_shadow_shadowmaplod = -1;
440         r_shadow_shadowmapsize = 0;
441         r_shadow_shadowmapsampler = false;
442         r_shadow_shadowmappcf = 0;
443         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
444         if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
445         {
446                 switch(vid.renderpath)
447                 {
448                 case RENDERPATH_GL20:
449                         if(r_shadow_shadowmapfilterquality < 0)
450                         {
451                                 if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
452                                         r_shadow_shadowmappcf = 1;
453                                 else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) 
454                                 {
455                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
456                                         r_shadow_shadowmappcf = 1;
457                                 }
458                                 else if(strstr(gl_vendor, "ATI")) 
459                                         r_shadow_shadowmappcf = 1;
460                                 else 
461                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
462                         }
463                         else 
464                         {
465                                 switch (r_shadow_shadowmapfilterquality)
466                                 {
467                                 case 1:
468                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
469                                         break;
470                                 case 2:
471                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
472                                         r_shadow_shadowmappcf = 1;
473                                         break;
474                                 case 3:
475                                         r_shadow_shadowmappcf = 1;
476                                         break;
477                                 case 4:
478                                         r_shadow_shadowmappcf = 2;
479                                         break;
480                                 }
481                         }
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
501 qboolean R_Shadow_ShadowMappingEnabled(void)
502 {
503         switch (r_shadow_shadowmode)
504         {
505         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
506                 return true;
507         default:
508                 return false;
509         }
510 }
511
512 void R_Shadow_FreeShadowMaps(void)
513 {
514         R_Shadow_SetShadowMode();
515
516         R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d);
517
518         r_shadow_fbo2d = 0;
519
520         if (r_shadow_shadowmap2dtexture)
521                 R_FreeTexture(r_shadow_shadowmap2dtexture);
522         r_shadow_shadowmap2dtexture = NULL;
523
524         if (r_shadow_shadowmap2dcolortexture)
525                 R_FreeTexture(r_shadow_shadowmap2dcolortexture);
526         r_shadow_shadowmap2dcolortexture = NULL;
527
528         if (r_shadow_shadowmapvsdcttexture)
529                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
530         r_shadow_shadowmapvsdcttexture = NULL;
531 }
532
533 void r_shadow_start(void)
534 {
535         // allocate vertex processing arrays
536         r_shadow_bouncegridpixels = NULL;
537         r_shadow_bouncegridhighpixels = NULL;
538         r_shadow_bouncegridnumpixels = 0;
539         r_shadow_bouncegridtexture = NULL;
540         r_shadow_bouncegriddirectional = false;
541         r_shadow_attenuationgradienttexture = NULL;
542         r_shadow_attenuation2dtexture = NULL;
543         r_shadow_attenuation3dtexture = NULL;
544         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
545         r_shadow_shadowmap2dtexture = NULL;
546         r_shadow_shadowmap2dcolortexture = NULL;
547         r_shadow_shadowmapvsdcttexture = NULL;
548         r_shadow_shadowmapmaxsize = 0;
549         r_shadow_shadowmapsize = 0;
550         r_shadow_shadowmaplod = 0;
551         r_shadow_shadowmapfilterquality = -1;
552         r_shadow_shadowmapdepthbits = 0;
553         r_shadow_shadowmapvsdct = false;
554         r_shadow_shadowmapsampler = false;
555         r_shadow_shadowmappcf = 0;
556         r_shadow_fbo2d = 0;
557
558         R_Shadow_FreeShadowMaps();
559
560         r_shadow_texturepool = NULL;
561         r_shadow_filters_texturepool = NULL;
562         R_Shadow_ValidateCvars();
563         R_Shadow_MakeTextures();
564         maxshadowtriangles = 0;
565         shadowelements = NULL;
566         maxshadowvertices = 0;
567         shadowvertex3f = NULL;
568         maxvertexupdate = 0;
569         vertexupdate = NULL;
570         vertexremap = NULL;
571         vertexupdatenum = 0;
572         maxshadowmark = 0;
573         numshadowmark = 0;
574         shadowmark = NULL;
575         shadowmarklist = NULL;
576         shadowmarkcount = 0;
577         maxshadowsides = 0;
578         numshadowsides = 0;
579         shadowsides = NULL;
580         shadowsideslist = NULL;
581         r_shadow_buffer_numleafpvsbytes = 0;
582         r_shadow_buffer_visitingleafpvs = NULL;
583         r_shadow_buffer_leafpvs = NULL;
584         r_shadow_buffer_leaflist = NULL;
585         r_shadow_buffer_numsurfacepvsbytes = 0;
586         r_shadow_buffer_surfacepvs = NULL;
587         r_shadow_buffer_surfacelist = NULL;
588         r_shadow_buffer_surfacesides = NULL;
589         r_shadow_buffer_numshadowtrispvsbytes = 0;
590         r_shadow_buffer_shadowtrispvs = NULL;
591         r_shadow_buffer_numlighttrispvsbytes = 0;
592         r_shadow_buffer_lighttrispvs = NULL;
593
594         r_shadow_usingdeferredprepass = false;
595         r_shadow_prepass_width = r_shadow_prepass_height = 0;
596 }
597
598 static void R_Shadow_FreeDeferred(void);
599 void r_shadow_shutdown(void)
600 {
601         CHECKGLERROR
602         R_Shadow_UncompileWorldLights();
603
604         R_Shadow_FreeShadowMaps();
605
606         r_shadow_usingdeferredprepass = false;
607         if (r_shadow_prepass_width)
608                 R_Shadow_FreeDeferred();
609         r_shadow_prepass_width = r_shadow_prepass_height = 0;
610
611         CHECKGLERROR
612         r_shadow_bouncegridtexture = NULL;
613         r_shadow_bouncegridpixels = NULL;
614         r_shadow_bouncegridhighpixels = NULL;
615         r_shadow_bouncegridnumpixels = 0;
616         r_shadow_bouncegriddirectional = false;
617         r_shadow_attenuationgradienttexture = NULL;
618         r_shadow_attenuation2dtexture = NULL;
619         r_shadow_attenuation3dtexture = NULL;
620         R_FreeTexturePool(&r_shadow_texturepool);
621         R_FreeTexturePool(&r_shadow_filters_texturepool);
622         maxshadowtriangles = 0;
623         if (shadowelements)
624                 Mem_Free(shadowelements);
625         shadowelements = NULL;
626         if (shadowvertex3f)
627                 Mem_Free(shadowvertex3f);
628         shadowvertex3f = NULL;
629         maxvertexupdate = 0;
630         if (vertexupdate)
631                 Mem_Free(vertexupdate);
632         vertexupdate = NULL;
633         if (vertexremap)
634                 Mem_Free(vertexremap);
635         vertexremap = NULL;
636         vertexupdatenum = 0;
637         maxshadowmark = 0;
638         numshadowmark = 0;
639         if (shadowmark)
640                 Mem_Free(shadowmark);
641         shadowmark = NULL;
642         if (shadowmarklist)
643                 Mem_Free(shadowmarklist);
644         shadowmarklist = NULL;
645         shadowmarkcount = 0;
646         maxshadowsides = 0;
647         numshadowsides = 0;
648         if (shadowsides)
649                 Mem_Free(shadowsides);
650         shadowsides = NULL;
651         if (shadowsideslist)
652                 Mem_Free(shadowsideslist);
653         shadowsideslist = NULL;
654         r_shadow_buffer_numleafpvsbytes = 0;
655         if (r_shadow_buffer_visitingleafpvs)
656                 Mem_Free(r_shadow_buffer_visitingleafpvs);
657         r_shadow_buffer_visitingleafpvs = NULL;
658         if (r_shadow_buffer_leafpvs)
659                 Mem_Free(r_shadow_buffer_leafpvs);
660         r_shadow_buffer_leafpvs = NULL;
661         if (r_shadow_buffer_leaflist)
662                 Mem_Free(r_shadow_buffer_leaflist);
663         r_shadow_buffer_leaflist = NULL;
664         r_shadow_buffer_numsurfacepvsbytes = 0;
665         if (r_shadow_buffer_surfacepvs)
666                 Mem_Free(r_shadow_buffer_surfacepvs);
667         r_shadow_buffer_surfacepvs = NULL;
668         if (r_shadow_buffer_surfacelist)
669                 Mem_Free(r_shadow_buffer_surfacelist);
670         r_shadow_buffer_surfacelist = NULL;
671         if (r_shadow_buffer_surfacesides)
672                 Mem_Free(r_shadow_buffer_surfacesides);
673         r_shadow_buffer_surfacesides = NULL;
674         r_shadow_buffer_numshadowtrispvsbytes = 0;
675         if (r_shadow_buffer_shadowtrispvs)
676                 Mem_Free(r_shadow_buffer_shadowtrispvs);
677         r_shadow_buffer_numlighttrispvsbytes = 0;
678         if (r_shadow_buffer_lighttrispvs)
679                 Mem_Free(r_shadow_buffer_lighttrispvs);
680 }
681
682 void r_shadow_newmap(void)
683 {
684         if (r_shadow_bouncegridtexture) R_FreeTexture(r_shadow_bouncegridtexture);r_shadow_bouncegridtexture = NULL;
685         if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
686         if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
687         if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
688         if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
689         if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
690         if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
691         if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
692         if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
693                 R_Shadow_EditLights_Reload_f();
694 }
695
696 void R_Shadow_Init(void)
697 {
698         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
699         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
700         Cvar_RegisterVariable(&r_shadow_usebihculling);
701         Cvar_RegisterVariable(&r_shadow_usenormalmap);
702         Cvar_RegisterVariable(&r_shadow_debuglight);
703         Cvar_RegisterVariable(&r_shadow_deferred);
704         Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
705 //      Cvar_RegisterVariable(&r_shadow_deferred_fp);
706         Cvar_RegisterVariable(&r_shadow_gloss);
707         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
708         Cvar_RegisterVariable(&r_shadow_glossintensity);
709         Cvar_RegisterVariable(&r_shadow_glossexponent);
710         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
711         Cvar_RegisterVariable(&r_shadow_glossexact);
712         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
713         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
714         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
715         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
716         Cvar_RegisterVariable(&r_shadow_projectdistance);
717         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
718         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
719         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
720         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
721         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
722         Cvar_RegisterVariable(&r_shadow_realtime_world);
723         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
724         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
725         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
726         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
727         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
728         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
729         Cvar_RegisterVariable(&r_shadow_scissor);
730         Cvar_RegisterVariable(&r_shadow_shadowmapping);
731         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
732         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
733         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
734         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
735         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
736         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
737 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
738 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
739         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
740         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
741         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
742         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
743         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
744         Cvar_RegisterVariable(&r_shadow_sortsurfaces);
745         Cvar_RegisterVariable(&r_shadow_polygonfactor);
746         Cvar_RegisterVariable(&r_shadow_polygonoffset);
747         Cvar_RegisterVariable(&r_shadow_texture3d);
748         Cvar_RegisterVariable(&r_shadow_bouncegrid);
749         Cvar_RegisterVariable(&r_shadow_bouncegrid_bounceanglediffuse);
750         Cvar_RegisterVariable(&r_shadow_bouncegrid_directionalshading);
751         Cvar_RegisterVariable(&r_shadow_bouncegrid_dlightparticlemultiplier);
752         Cvar_RegisterVariable(&r_shadow_bouncegrid_hitmodels);
753         Cvar_RegisterVariable(&r_shadow_bouncegrid_includedirectlighting);
754         Cvar_RegisterVariable(&r_shadow_bouncegrid_intensity);
755         Cvar_RegisterVariable(&r_shadow_bouncegrid_lightradiusscale);
756         Cvar_RegisterVariable(&r_shadow_bouncegrid_maxbounce);
757         Cvar_RegisterVariable(&r_shadow_bouncegrid_particlebounceintensity);
758         Cvar_RegisterVariable(&r_shadow_bouncegrid_particleintensity);
759         Cvar_RegisterVariable(&r_shadow_bouncegrid_photons);
760         Cvar_RegisterVariable(&r_shadow_bouncegrid_spacing);
761         Cvar_RegisterVariable(&r_shadow_bouncegrid_stablerandom);
762         Cvar_RegisterVariable(&r_shadow_bouncegrid_static);
763         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_directionalshading);
764         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_lightradiusscale);
765         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxbounce);
766         Cvar_RegisterVariable(&r_shadow_bouncegrid_static_photons);
767         Cvar_RegisterVariable(&r_shadow_bouncegrid_updateinterval);
768         Cvar_RegisterVariable(&r_shadow_bouncegrid_x);
769         Cvar_RegisterVariable(&r_shadow_bouncegrid_y);
770         Cvar_RegisterVariable(&r_shadow_bouncegrid_z);
771         Cvar_RegisterVariable(&r_coronas);
772         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
773         Cvar_RegisterVariable(&r_coronas_occlusionquery);
774         Cvar_RegisterVariable(&gl_flashblend);
775         Cvar_RegisterVariable(&gl_ext_separatestencil);
776         Cvar_RegisterVariable(&gl_ext_stenciltwoside);
777         R_Shadow_EditLights_Init();
778         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
779         maxshadowtriangles = 0;
780         shadowelements = NULL;
781         maxshadowvertices = 0;
782         shadowvertex3f = NULL;
783         maxvertexupdate = 0;
784         vertexupdate = NULL;
785         vertexremap = NULL;
786         vertexupdatenum = 0;
787         maxshadowmark = 0;
788         numshadowmark = 0;
789         shadowmark = NULL;
790         shadowmarklist = NULL;
791         shadowmarkcount = 0;
792         maxshadowsides = 0;
793         numshadowsides = 0;
794         shadowsides = NULL;
795         shadowsideslist = NULL;
796         r_shadow_buffer_numleafpvsbytes = 0;
797         r_shadow_buffer_visitingleafpvs = NULL;
798         r_shadow_buffer_leafpvs = NULL;
799         r_shadow_buffer_leaflist = NULL;
800         r_shadow_buffer_numsurfacepvsbytes = 0;
801         r_shadow_buffer_surfacepvs = NULL;
802         r_shadow_buffer_surfacelist = NULL;
803         r_shadow_buffer_surfacesides = NULL;
804         r_shadow_buffer_shadowtrispvs = NULL;
805         r_shadow_buffer_lighttrispvs = NULL;
806         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap, NULL, NULL);
807 }
808
809 matrix4x4_t matrix_attenuationxyz =
810 {
811         {
812                 {0.5, 0.0, 0.0, 0.5},
813                 {0.0, 0.5, 0.0, 0.5},
814                 {0.0, 0.0, 0.5, 0.5},
815                 {0.0, 0.0, 0.0, 1.0}
816         }
817 };
818
819 matrix4x4_t matrix_attenuationz =
820 {
821         {
822                 {0.0, 0.0, 0.5, 0.5},
823                 {0.0, 0.0, 0.0, 0.5},
824                 {0.0, 0.0, 0.0, 0.5},
825                 {0.0, 0.0, 0.0, 1.0}
826         }
827 };
828
829 void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
830 {
831         numvertices = ((numvertices + 255) & ~255) * vertscale;
832         numtriangles = ((numtriangles + 255) & ~255) * triscale;
833         // make sure shadowelements is big enough for this volume
834         if (maxshadowtriangles < numtriangles)
835         {
836                 maxshadowtriangles = numtriangles;
837                 if (shadowelements)
838                         Mem_Free(shadowelements);
839                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
840         }
841         // make sure shadowvertex3f is big enough for this volume
842         if (maxshadowvertices < numvertices)
843         {
844                 maxshadowvertices = numvertices;
845                 if (shadowvertex3f)
846                         Mem_Free(shadowvertex3f);
847                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
848         }
849 }
850
851 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
852 {
853         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
854         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
855         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
856         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
857         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
858         {
859                 if (r_shadow_buffer_visitingleafpvs)
860                         Mem_Free(r_shadow_buffer_visitingleafpvs);
861                 if (r_shadow_buffer_leafpvs)
862                         Mem_Free(r_shadow_buffer_leafpvs);
863                 if (r_shadow_buffer_leaflist)
864                         Mem_Free(r_shadow_buffer_leaflist);
865                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
866                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
867                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
868                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
869         }
870         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
871         {
872                 if (r_shadow_buffer_surfacepvs)
873                         Mem_Free(r_shadow_buffer_surfacepvs);
874                 if (r_shadow_buffer_surfacelist)
875                         Mem_Free(r_shadow_buffer_surfacelist);
876                 if (r_shadow_buffer_surfacesides)
877                         Mem_Free(r_shadow_buffer_surfacesides);
878                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
879                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
880                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
881                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
882         }
883         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
884         {
885                 if (r_shadow_buffer_shadowtrispvs)
886                         Mem_Free(r_shadow_buffer_shadowtrispvs);
887                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
888                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
889         }
890         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
891         {
892                 if (r_shadow_buffer_lighttrispvs)
893                         Mem_Free(r_shadow_buffer_lighttrispvs);
894                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
895                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
896         }
897 }
898
899 void R_Shadow_PrepareShadowMark(int numtris)
900 {
901         // make sure shadowmark is big enough for this volume
902         if (maxshadowmark < numtris)
903         {
904                 maxshadowmark = numtris;
905                 if (shadowmark)
906                         Mem_Free(shadowmark);
907                 if (shadowmarklist)
908                         Mem_Free(shadowmarklist);
909                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
910                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
911                 shadowmarkcount = 0;
912         }
913         shadowmarkcount++;
914         // if shadowmarkcount wrapped we clear the array and adjust accordingly
915         if (shadowmarkcount == 0)
916         {
917                 shadowmarkcount = 1;
918                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
919         }
920         numshadowmark = 0;
921 }
922
923 void R_Shadow_PrepareShadowSides(int numtris)
924 {
925     if (maxshadowsides < numtris)
926     {
927         maxshadowsides = numtris;
928         if (shadowsides)
929                         Mem_Free(shadowsides);
930                 if (shadowsideslist)
931                         Mem_Free(shadowsideslist);
932                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
933                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
934         }
935         numshadowsides = 0;
936 }
937
938 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)
939 {
940         int i, j;
941         int outtriangles = 0, outvertices = 0;
942         const int *element;
943         const float *vertex;
944         float ratio, direction[3], projectvector[3];
945
946         if (projectdirection)
947                 VectorScale(projectdirection, projectdistance, projectvector);
948         else
949                 VectorClear(projectvector);
950
951         // create the vertices
952         if (projectdirection)
953         {
954                 for (i = 0;i < numshadowmarktris;i++)
955                 {
956                         element = inelement3i + shadowmarktris[i] * 3;
957                         for (j = 0;j < 3;j++)
958                         {
959                                 if (vertexupdate[element[j]] != vertexupdatenum)
960                                 {
961                                         vertexupdate[element[j]] = vertexupdatenum;
962                                         vertexremap[element[j]] = outvertices;
963                                         vertex = invertex3f + element[j] * 3;
964                                         // project one copy of the vertex according to projectvector
965                                         VectorCopy(vertex, outvertex3f);
966                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
967                                         outvertex3f += 6;
968                                         outvertices += 2;
969                                 }
970                         }
971                 }
972         }
973         else
974         {
975                 for (i = 0;i < numshadowmarktris;i++)
976                 {
977                         element = inelement3i + shadowmarktris[i] * 3;
978                         for (j = 0;j < 3;j++)
979                         {
980                                 if (vertexupdate[element[j]] != vertexupdatenum)
981                                 {
982                                         vertexupdate[element[j]] = vertexupdatenum;
983                                         vertexremap[element[j]] = outvertices;
984                                         vertex = invertex3f + element[j] * 3;
985                                         // project one copy of the vertex to the sphere radius of the light
986                                         // (FIXME: would projecting it to the light box be better?)
987                                         VectorSubtract(vertex, projectorigin, direction);
988                                         ratio = projectdistance / VectorLength(direction);
989                                         VectorCopy(vertex, outvertex3f);
990                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
991                                         outvertex3f += 6;
992                                         outvertices += 2;
993                                 }
994                         }
995                 }
996         }
997
998         if (r_shadow_frontsidecasting.integer)
999         {
1000                 for (i = 0;i < numshadowmarktris;i++)
1001                 {
1002                         int remappedelement[3];
1003                         int markindex;
1004                         const int *neighbortriangle;
1005
1006                         markindex = shadowmarktris[i] * 3;
1007                         element = inelement3i + markindex;
1008                         neighbortriangle = inneighbor3i + markindex;
1009                         // output the front and back triangles
1010                         outelement3i[0] = vertexremap[element[0]];
1011                         outelement3i[1] = vertexremap[element[1]];
1012                         outelement3i[2] = vertexremap[element[2]];
1013                         outelement3i[3] = vertexremap[element[2]] + 1;
1014                         outelement3i[4] = vertexremap[element[1]] + 1;
1015                         outelement3i[5] = vertexremap[element[0]] + 1;
1016
1017                         outelement3i += 6;
1018                         outtriangles += 2;
1019                         // output the sides (facing outward from this triangle)
1020                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1021                         {
1022                                 remappedelement[0] = vertexremap[element[0]];
1023                                 remappedelement[1] = vertexremap[element[1]];
1024                                 outelement3i[0] = remappedelement[1];
1025                                 outelement3i[1] = remappedelement[0];
1026                                 outelement3i[2] = remappedelement[0] + 1;
1027                                 outelement3i[3] = remappedelement[1];
1028                                 outelement3i[4] = remappedelement[0] + 1;
1029                                 outelement3i[5] = remappedelement[1] + 1;
1030
1031                                 outelement3i += 6;
1032                                 outtriangles += 2;
1033                         }
1034                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1035                         {
1036                                 remappedelement[1] = vertexremap[element[1]];
1037                                 remappedelement[2] = vertexremap[element[2]];
1038                                 outelement3i[0] = remappedelement[2];
1039                                 outelement3i[1] = remappedelement[1];
1040                                 outelement3i[2] = remappedelement[1] + 1;
1041                                 outelement3i[3] = remappedelement[2];
1042                                 outelement3i[4] = remappedelement[1] + 1;
1043                                 outelement3i[5] = remappedelement[2] + 1;
1044
1045                                 outelement3i += 6;
1046                                 outtriangles += 2;
1047                         }
1048                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1049                         {
1050                                 remappedelement[0] = vertexremap[element[0]];
1051                                 remappedelement[2] = vertexremap[element[2]];
1052                                 outelement3i[0] = remappedelement[0];
1053                                 outelement3i[1] = remappedelement[2];
1054                                 outelement3i[2] = remappedelement[2] + 1;
1055                                 outelement3i[3] = remappedelement[0];
1056                                 outelement3i[4] = remappedelement[2] + 1;
1057                                 outelement3i[5] = remappedelement[0] + 1;
1058
1059                                 outelement3i += 6;
1060                                 outtriangles += 2;
1061                         }
1062                 }
1063         }
1064         else
1065         {
1066                 for (i = 0;i < numshadowmarktris;i++)
1067                 {
1068                         int remappedelement[3];
1069                         int markindex;
1070                         const int *neighbortriangle;
1071
1072                         markindex = shadowmarktris[i] * 3;
1073                         element = inelement3i + markindex;
1074                         neighbortriangle = inneighbor3i + markindex;
1075                         // output the front and back triangles
1076                         outelement3i[0] = vertexremap[element[2]];
1077                         outelement3i[1] = vertexremap[element[1]];
1078                         outelement3i[2] = vertexremap[element[0]];
1079                         outelement3i[3] = vertexremap[element[0]] + 1;
1080                         outelement3i[4] = vertexremap[element[1]] + 1;
1081                         outelement3i[5] = vertexremap[element[2]] + 1;
1082
1083                         outelement3i += 6;
1084                         outtriangles += 2;
1085                         // output the sides (facing outward from this triangle)
1086                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1087                         {
1088                                 remappedelement[0] = vertexremap[element[0]];
1089                                 remappedelement[1] = vertexremap[element[1]];
1090                                 outelement3i[0] = remappedelement[0];
1091                                 outelement3i[1] = remappedelement[1];
1092                                 outelement3i[2] = remappedelement[1] + 1;
1093                                 outelement3i[3] = remappedelement[0];
1094                                 outelement3i[4] = remappedelement[1] + 1;
1095                                 outelement3i[5] = remappedelement[0] + 1;
1096
1097                                 outelement3i += 6;
1098                                 outtriangles += 2;
1099                         }
1100                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1101                         {
1102                                 remappedelement[1] = vertexremap[element[1]];
1103                                 remappedelement[2] = vertexremap[element[2]];
1104                                 outelement3i[0] = remappedelement[1];
1105                                 outelement3i[1] = remappedelement[2];
1106                                 outelement3i[2] = remappedelement[2] + 1;
1107                                 outelement3i[3] = remappedelement[1];
1108                                 outelement3i[4] = remappedelement[2] + 1;
1109                                 outelement3i[5] = remappedelement[1] + 1;
1110
1111                                 outelement3i += 6;
1112                                 outtriangles += 2;
1113                         }
1114                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1115                         {
1116                                 remappedelement[0] = vertexremap[element[0]];
1117                                 remappedelement[2] = vertexremap[element[2]];
1118                                 outelement3i[0] = remappedelement[2];
1119                                 outelement3i[1] = remappedelement[0];
1120                                 outelement3i[2] = remappedelement[0] + 1;
1121                                 outelement3i[3] = remappedelement[2];
1122                                 outelement3i[4] = remappedelement[0] + 1;
1123                                 outelement3i[5] = remappedelement[2] + 1;
1124
1125                                 outelement3i += 6;
1126                                 outtriangles += 2;
1127                         }
1128                 }
1129         }
1130         if (outnumvertices)
1131                 *outnumvertices = outvertices;
1132         return outtriangles;
1133 }
1134
1135 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)
1136 {
1137         int i, j, k;
1138         int outtriangles = 0, outvertices = 0;
1139         const int *element;
1140         const float *vertex;
1141         float ratio, direction[3], projectvector[3];
1142         qboolean side[4];
1143
1144         if (projectdirection)
1145                 VectorScale(projectdirection, projectdistance, projectvector);
1146         else
1147                 VectorClear(projectvector);
1148
1149         for (i = 0;i < numshadowmarktris;i++)
1150         {
1151                 int remappedelement[3];
1152                 int markindex;
1153                 const int *neighbortriangle;
1154
1155                 markindex = shadowmarktris[i] * 3;
1156                 neighbortriangle = inneighbor3i + markindex;
1157                 side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
1158                 side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
1159                 side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
1160                 if (side[0] + side[1] + side[2] == 0)
1161                         continue;
1162
1163                 side[3] = side[0];
1164                 element = inelement3i + markindex;
1165
1166                 // create the vertices
1167                 for (j = 0;j < 3;j++)
1168                 {
1169                         if (side[j] + side[j+1] == 0)
1170                                 continue;
1171                         k = element[j];
1172                         if (vertexupdate[k] != vertexupdatenum)
1173                         {
1174                                 vertexupdate[k] = vertexupdatenum;
1175                                 vertexremap[k] = outvertices;
1176                                 vertex = invertex3f + k * 3;
1177                                 VectorCopy(vertex, outvertex3f);
1178                                 if (projectdirection)
1179                                 {
1180                                         // project one copy of the vertex according to projectvector
1181                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1182                                 }
1183                                 else
1184                                 {
1185                                         // project one copy of the vertex to the sphere radius of the light
1186                                         // (FIXME: would projecting it to the light box be better?)
1187                                         VectorSubtract(vertex, projectorigin, direction);
1188                                         ratio = projectdistance / VectorLength(direction);
1189                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1190                                 }
1191                                 outvertex3f += 6;
1192                                 outvertices += 2;
1193                         }
1194                 }
1195
1196                 // output the sides (facing outward from this triangle)
1197                 if (!side[0])
1198                 {
1199                         remappedelement[0] = vertexremap[element[0]];
1200                         remappedelement[1] = vertexremap[element[1]];
1201                         outelement3i[0] = remappedelement[1];
1202                         outelement3i[1] = remappedelement[0];
1203                         outelement3i[2] = remappedelement[0] + 1;
1204                         outelement3i[3] = remappedelement[1];
1205                         outelement3i[4] = remappedelement[0] + 1;
1206                         outelement3i[5] = remappedelement[1] + 1;
1207
1208                         outelement3i += 6;
1209                         outtriangles += 2;
1210                 }
1211                 if (!side[1])
1212                 {
1213                         remappedelement[1] = vertexremap[element[1]];
1214                         remappedelement[2] = vertexremap[element[2]];
1215                         outelement3i[0] = remappedelement[2];
1216                         outelement3i[1] = remappedelement[1];
1217                         outelement3i[2] = remappedelement[1] + 1;
1218                         outelement3i[3] = remappedelement[2];
1219                         outelement3i[4] = remappedelement[1] + 1;
1220                         outelement3i[5] = remappedelement[2] + 1;
1221
1222                         outelement3i += 6;
1223                         outtriangles += 2;
1224                 }
1225                 if (!side[2])
1226                 {
1227                         remappedelement[0] = vertexremap[element[0]];
1228                         remappedelement[2] = vertexremap[element[2]];
1229                         outelement3i[0] = remappedelement[0];
1230                         outelement3i[1] = remappedelement[2];
1231                         outelement3i[2] = remappedelement[2] + 1;
1232                         outelement3i[3] = remappedelement[0];
1233                         outelement3i[4] = remappedelement[2] + 1;
1234                         outelement3i[5] = remappedelement[0] + 1;
1235
1236                         outelement3i += 6;
1237                         outtriangles += 2;
1238                 }
1239         }
1240         if (outnumvertices)
1241                 *outnumvertices = outvertices;
1242         return outtriangles;
1243 }
1244
1245 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)
1246 {
1247         int t, tend;
1248         const int *e;
1249         const float *v[3];
1250         float normal[3];
1251         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1252                 return;
1253         tend = firsttriangle + numtris;
1254         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1255         {
1256                 // surface box entirely inside light box, no box cull
1257                 if (projectdirection)
1258                 {
1259                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1260                         {
1261                                 TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
1262                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1263                                         shadowmarklist[numshadowmark++] = t;
1264                         }
1265                 }
1266                 else
1267                 {
1268                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1269                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
1270                                         shadowmarklist[numshadowmark++] = t;
1271                 }
1272         }
1273         else
1274         {
1275                 // surface box not entirely inside light box, cull each triangle
1276                 if (projectdirection)
1277                 {
1278                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1279                         {
1280                                 v[0] = invertex3f + e[0] * 3;
1281                                 v[1] = invertex3f + e[1] * 3;
1282                                 v[2] = invertex3f + e[2] * 3;
1283                                 TriangleNormal(v[0], v[1], v[2], normal);
1284                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1285                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1286                                         shadowmarklist[numshadowmark++] = t;
1287                         }
1288                 }
1289                 else
1290                 {
1291                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1292                         {
1293                                 v[0] = invertex3f + e[0] * 3;
1294                                 v[1] = invertex3f + e[1] * 3;
1295                                 v[2] = invertex3f + e[2] * 3;
1296                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1297                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1298                                         shadowmarklist[numshadowmark++] = t;
1299                         }
1300                 }
1301         }
1302 }
1303
1304 qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
1305 {
1306 #if 1
1307         return false;
1308 #else
1309         if (r_shadow_compilingrtlight || !r_shadow_frontsidecasting.integer || !r_shadow_usezpassifpossible.integer)
1310                 return false;
1311         // check if the shadow volume intersects the near plane
1312         //
1313         // a ray between the eye and light origin may intersect the caster,
1314         // indicating that the shadow may touch the eye location, however we must
1315         // test the near plane (a polygon), not merely the eye location, so it is
1316         // easiest to enlarge the caster bounding shape slightly for this.
1317         // TODO
1318         return true;
1319 #endif
1320 }
1321
1322 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)
1323 {
1324         int i, tris, outverts;
1325         if (projectdistance < 0.1)
1326         {
1327                 Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
1328                 return;
1329         }
1330         if (!numverts || !nummarktris)
1331                 return;
1332         // make sure shadowelements is big enough for this volume
1333         if (maxshadowtriangles < nummarktris*8 || maxshadowvertices < numverts*2)
1334                 R_Shadow_ResizeShadowArrays(numverts, nummarktris, 2, 8);
1335
1336         if (maxvertexupdate < numverts)
1337         {
1338                 maxvertexupdate = numverts;
1339                 if (vertexupdate)
1340                         Mem_Free(vertexupdate);
1341                 if (vertexremap)
1342                         Mem_Free(vertexremap);
1343                 vertexupdate = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1344                 vertexremap = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1345                 vertexupdatenum = 0;
1346         }
1347         vertexupdatenum++;
1348         if (vertexupdatenum == 0)
1349         {
1350                 vertexupdatenum = 1;
1351                 memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
1352                 memset(vertexremap, 0, maxvertexupdate * sizeof(int));
1353         }
1354
1355         for (i = 0;i < nummarktris;i++)
1356                 shadowmark[marktris[i]] = shadowmarkcount;
1357
1358         if (r_shadow_compilingrtlight)
1359         {
1360                 // if we're compiling an rtlight, capture the mesh
1361                 //tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1362                 //Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zpass, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1363                 tris = R_Shadow_ConstructShadowVolume_ZFail(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_zfail, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1365         }
1366         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1367         {
1368                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1369                 R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
1370                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1371         }
1372         else
1373         {
1374                 // decide which type of shadow to generate and set stencil mode
1375                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1376                 // generate the sides or a solid volume, depending on type
1377                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1378                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1379                 else
1380                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1381                 r_refdef.stats.lights_dynamicshadowtriangles += tris;
1382                 r_refdef.stats.lights_shadowtriangles += tris;
1383                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1384                 {
1385                         // increment stencil if frontface is infront of depthbuffer
1386                         GL_CullFace(r_refdef.view.cullface_front);
1387                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
1388                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1389                         // decrement stencil if backface is infront of depthbuffer
1390                         GL_CullFace(r_refdef.view.cullface_back);
1391                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
1392                 }
1393                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1394                 {
1395                         // decrement stencil if backface is behind depthbuffer
1396                         GL_CullFace(r_refdef.view.cullface_front);
1397                         R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
1398                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1399                         // increment stencil if frontface is behind depthbuffer
1400                         GL_CullFace(r_refdef.view.cullface_back);
1401                         R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
1402                 }
1403                 R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
1404                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1405         }
1406 }
1407
1408 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1409 {
1410     // p1, p2, p3 are in the cubemap's local coordinate system
1411     // bias = border/(size - border)
1412         int mask = 0x3F;
1413
1414     float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1415           dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1416           dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1417         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1418         mask &= (3<<4)
1419                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1420                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1421                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1422     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1423         mask &= (3<<4)
1424             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1425             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))            
1426             | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1427
1428     dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1429     dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1430     dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1431     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1432         mask &= (3<<0)
1433             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1434             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))            
1435             | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1436     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1437         mask &= (3<<0)
1438             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1439             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1440             | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1441
1442     dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1443     dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1444     dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1445     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1446         mask &= (3<<2)
1447             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1448             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1449             | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1450     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1451         mask &= (3<<2)
1452             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1453             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1454             | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1455
1456         return mask;
1457 }
1458
1459 int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1460 {
1461         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1462         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1463         int mask = 0x3F;
1464
1465         VectorSubtract(maxs, mins, radius);
1466     VectorScale(radius, 0.5f, radius);
1467     VectorAdd(mins, radius, center);
1468     Matrix4x4_Transform(worldtolight, center, lightcenter);
1469         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1470         VectorSubtract(lightcenter, lightradius, pmin);
1471         VectorAdd(lightcenter, lightradius, pmax);
1472
1473     dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1474     dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1475     if(ap1 > bias*an1 && ap2 > bias*an2)
1476         mask &= (3<<4)
1477             | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1478             | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1479     if(an1 > bias*ap1 && an2 > bias*ap2)
1480         mask &= (3<<4)
1481             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1482             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1483
1484     dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1485     dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1486     if(ap1 > bias*an1 && ap2 > bias*an2)
1487         mask &= (3<<0)
1488             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1489             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1490     if(an1 > bias*ap1 && an2 > bias*ap2)
1491         mask &= (3<<0)
1492             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1493             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1494
1495     dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1496     dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1497     if(ap1 > bias*an1 && ap2 > bias*an2)
1498         mask &= (3<<2)
1499             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1500             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1501     if(an1 > bias*ap1 && an2 > bias*ap2)
1502         mask &= (3<<2)
1503             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1504             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1505
1506     return mask;
1507 }
1508
1509 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1510
1511 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1512 {
1513     // p is in the cubemap's local coordinate system
1514     // bias = border/(size - border)
1515     float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1516     float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1517     float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1518     int mask = 0x3F;
1519     if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1520     if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1521     if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1522     if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1523     if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1524     if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1525     return mask;
1526 }
1527
1528 int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1529 {
1530         int i;
1531         vec3_t p, n;
1532         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1533         float scale = (size - 2*border)/size, len;
1534         float bias = border / (float)(size - border), dp, dn, ap, an;
1535         // check if cone enclosing side would cross frustum plane 
1536         scale = 2 / (scale*scale + 2);
1537         for (i = 0;i < 5;i++)
1538         {
1539                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
1540                         continue;
1541                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1542                 len = scale*VectorLength2(n);
1543                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1544                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1545                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1546         }
1547         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1548         {
1549         Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1550         len = scale*VectorLength(n);
1551                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1552                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1553                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1554         }
1555         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1556         // check if frustum corners/origin cross plane sides
1557 #if 1
1558     // infinite version, assumes frustum corners merely give direction and extend to infinite distance
1559     Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
1560     dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1561     masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1562     masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1563     dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1564     masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1565     masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1566     dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1567     masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1568     masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1569     for (i = 0;i < 4;i++)
1570     {
1571         Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
1572         VectorSubtract(n, p, n);
1573         dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
1574         if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
1575         if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
1576         dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
1577         if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
1578         if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
1579         dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
1580         if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
1581         if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
1582     }
1583 #else
1584     // finite version, assumes corners are a finite distance from origin dependent on far plane
1585         for (i = 0;i < 5;i++)
1586         {
1587                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1588                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1589                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1590                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1591                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1592                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1593                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1594                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1595                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1596                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1597         }
1598 #endif
1599         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1600 }
1601
1602 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)
1603 {
1604         int t, tend;
1605         const int *e;
1606         const float *v[3];
1607         float normal[3];
1608         vec3_t p[3];
1609         float bias;
1610         int mask, surfacemask = 0;
1611         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1612                 return 0;
1613         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1614         tend = firsttriangle + numtris;
1615         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1616         {
1617                 // surface box entirely inside light box, no box cull
1618                 if (projectdirection)
1619                 {
1620                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1621                         {
1622                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1623                                 TriangleNormal(v[0], v[1], v[2], normal);
1624                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1625                                 {
1626                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1627                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1628                                         surfacemask |= mask;
1629                                         if(totals)
1630                                         {
1631                                                 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;
1632                                                 shadowsides[numshadowsides] = mask;
1633                                                 shadowsideslist[numshadowsides++] = t;
1634                                         }
1635                                 }
1636                         }
1637                 }
1638                 else
1639                 {
1640                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1641                         {
1642                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1643                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1644                                 {
1645                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1646                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1647                                         surfacemask |= mask;
1648                                         if(totals)
1649                                         {
1650                                                 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;
1651                                                 shadowsides[numshadowsides] = mask;
1652                                                 shadowsideslist[numshadowsides++] = t;
1653                                         }
1654                                 }
1655                         }
1656                 }
1657         }
1658         else
1659         {
1660                 // surface box not entirely inside light box, cull each triangle
1661                 if (projectdirection)
1662                 {
1663                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1664                         {
1665                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1666                                 TriangleNormal(v[0], v[1], v[2], normal);
1667                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1668                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1669                                 {
1670                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1671                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1672                                         surfacemask |= mask;
1673                                         if(totals)
1674                                         {
1675                                                 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;
1676                                                 shadowsides[numshadowsides] = mask;
1677                                                 shadowsideslist[numshadowsides++] = t;
1678                                         }
1679                                 }
1680                         }
1681                 }
1682                 else
1683                 {
1684                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1685                         {
1686                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1687                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1688                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1689                                 {
1690                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1691                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1692                                         surfacemask |= mask;
1693                                         if(totals)
1694                                         {
1695                                                 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;
1696                                                 shadowsides[numshadowsides] = mask;
1697                                                 shadowsideslist[numshadowsides++] = t;
1698                                         }
1699                                 }
1700                         }
1701                 }
1702         }
1703         return surfacemask;
1704 }
1705
1706 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)
1707 {
1708         int i, j, outtriangles = 0;
1709         int *outelement3i[6];
1710         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1711                 return;
1712         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1713         // make sure shadowelements is big enough for this mesh
1714         if (maxshadowtriangles < outtriangles)
1715                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1716
1717         // compute the offset and size of the separate index lists for each cubemap side
1718         outtriangles = 0;
1719         for (i = 0;i < 6;i++)
1720         {
1721                 outelement3i[i] = shadowelements + outtriangles * 3;
1722                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1723                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1724                 outtriangles += sidetotals[i];
1725         }
1726
1727         // gather up the (sparse) triangles into separate index lists for each cubemap side
1728         for (i = 0;i < numsidetris;i++)
1729         {
1730                 const int *element = elements + sidetris[i] * 3;
1731                 for (j = 0;j < 6;j++)
1732                 {
1733                         if (sides[i] & (1 << j))
1734                         {
1735                                 outelement3i[j][0] = element[0];
1736                                 outelement3i[j][1] = element[1];
1737                                 outelement3i[j][2] = element[2];
1738                                 outelement3i[j] += 3;
1739                         }
1740                 }
1741         }
1742                         
1743         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1744 }
1745
1746 static void R_Shadow_MakeTextures_MakeCorona(void)
1747 {
1748         float dx, dy;
1749         int x, y, a;
1750         unsigned char pixels[32][32][4];
1751         for (y = 0;y < 32;y++)
1752         {
1753                 dy = (y - 15.5f) * (1.0f / 16.0f);
1754                 for (x = 0;x < 32;x++)
1755                 {
1756                         dx = (x - 15.5f) * (1.0f / 16.0f);
1757                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1758                         a = bound(0, a, 255);
1759                         pixels[y][x][0] = a;
1760                         pixels[y][x][1] = a;
1761                         pixels[y][x][2] = a;
1762                         pixels[y][x][3] = 255;
1763                 }
1764         }
1765         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32, false);
1766 }
1767
1768 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1769 {
1770         float dist = sqrt(x*x+y*y+z*z);
1771         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1772         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1773         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1774 }
1775
1776 static void R_Shadow_MakeTextures(void)
1777 {
1778         int x, y, z;
1779         float intensity, dist;
1780         unsigned int *data;
1781         R_Shadow_FreeShadowMaps();
1782         R_FreeTexturePool(&r_shadow_texturepool);
1783         r_shadow_texturepool = R_AllocTexturePool();
1784         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1785         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1786         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1787         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1788         for (x = 0;x <= ATTENTABLESIZE;x++)
1789         {
1790                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1791                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1792                 r_shadow_attentable[x] = bound(0, intensity, 1);
1793         }
1794         // 1D gradient texture
1795         for (x = 0;x < ATTEN1DSIZE;x++)
1796                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1797         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1798         // 2D circle texture
1799         for (y = 0;y < ATTEN2DSIZE;y++)
1800                 for (x = 0;x < ATTEN2DSIZE;x++)
1801                         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);
1802         r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1803         // 3D sphere texture
1804         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1805         {
1806                 for (z = 0;z < ATTEN3DSIZE;z++)
1807                         for (y = 0;y < ATTEN3DSIZE;y++)
1808                                 for (x = 0;x < ATTEN3DSIZE;x++)
1809                                         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));
1810                 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);
1811         }
1812         else
1813                 r_shadow_attenuation3dtexture = NULL;
1814         Mem_Free(data);
1815
1816         R_Shadow_MakeTextures_MakeCorona();
1817
1818         // Editor light sprites
1819         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1820         "................"
1821         ".3............3."
1822         "..5...2332...5.."
1823         "...7.3....3.7..."
1824         "....7......7...."
1825         "...3.7....7.3..."
1826         "..2...7..7...2.."
1827         "..3..........3.."
1828         "..3..........3.."
1829         "..2...7..7...2.."
1830         "...3.7....7.3..."
1831         "....7......7...."
1832         "...7.3....3.7..."
1833         "..5...2332...5.."
1834         ".3............3."
1835         "................"
1836         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1837         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1838         "................"
1839         "................"
1840         "......1111......"
1841         "....11233211...."
1842         "...1234554321..."
1843         "...1356776531..."
1844         "..124677776421.."
1845         "..135777777531.."
1846         "..135777777531.."
1847         "..124677776421.."
1848         "...1356776531..."
1849         "...1234554321..."
1850         "....11233211...."
1851         "......1111......"
1852         "................"
1853         "................"
1854         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1855         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1856         "................"
1857         "................"
1858         "......1111......"
1859         "....11233211...."
1860         "...1234554321..."
1861         "...1356226531..."
1862         "..12462..26421.."
1863         "..1352....2531.."
1864         "..1352....2531.."
1865         "..12462..26421.."
1866         "...1356226531..."
1867         "...1234554321..."
1868         "....11233211...."
1869         "......1111......"
1870         "................"
1871         "................"
1872         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1873         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1874         "................"
1875         "................"
1876         "......2772......"
1877         "....27755772...."
1878         "..277533335772.."
1879         "..753333333357.."
1880         "..777533335777.."
1881         "..735775577537.."
1882         "..733357753337.."
1883         "..733337733337.."
1884         "..753337733357.."
1885         "..277537735772.."
1886         "....27777772...."
1887         "......2772......"
1888         "................"
1889         "................"
1890         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1891         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1892         "................"
1893         "................"
1894         "......2772......"
1895         "....27722772...."
1896         "..2772....2772.."
1897         "..72........27.."
1898         "..7772....2777.."
1899         "..7.27722772.7.."
1900         "..7...2772...7.."
1901         "..7....77....7.."
1902         "..72...77...27.."
1903         "..2772.77.2772.."
1904         "....27777772...."
1905         "......2772......"
1906         "................"
1907         "................"
1908         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1909         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1910         "................"
1911         ".777752..257777."
1912         ".742........247."
1913         ".72..........27."
1914         ".7............7."
1915         ".5............5."
1916         ".2............2."
1917         "................"
1918         "................"
1919         ".2............2."
1920         ".5............5."
1921         ".7............7."
1922         ".72..........27."
1923         ".742........247."
1924         ".777752..257777."
1925         "................"
1926         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1927 }
1928
1929 void R_Shadow_ValidateCvars(void)
1930 {
1931         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
1932                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
1933         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
1934                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
1935         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
1936                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
1937 }
1938
1939 void R_Shadow_RenderMode_Begin(void)
1940 {
1941 #if 0
1942         GLint drawbuffer;
1943         GLint readbuffer;
1944 #endif
1945         R_Shadow_ValidateCvars();
1946
1947         if (!r_shadow_attenuation2dtexture
1948          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
1949          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1950          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1951                 R_Shadow_MakeTextures();
1952
1953         CHECKGLERROR
1954         R_Mesh_ResetTextureState();
1955         GL_BlendFunc(GL_ONE, GL_ZERO);
1956         GL_DepthRange(0, 1);
1957         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1958         GL_DepthTest(true);
1959         GL_DepthMask(false);
1960         GL_Color(0, 0, 0, 1);
1961         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1962         
1963         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1964
1965         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
1966         {
1967                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
1968                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
1969         }
1970         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
1971         {
1972                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
1973                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
1974         }
1975         else
1976         {
1977                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
1978                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
1979         }
1980
1981         switch(vid.renderpath)
1982         {
1983         case RENDERPATH_GL20:
1984         case RENDERPATH_D3D9:
1985         case RENDERPATH_D3D10:
1986         case RENDERPATH_D3D11:
1987         case RENDERPATH_SOFT:
1988         case RENDERPATH_GLES2:
1989                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1990                 break;
1991         case RENDERPATH_GL11:
1992         case RENDERPATH_GL13:
1993         case RENDERPATH_GLES1:
1994                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
1995                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
1996                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
1997                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
1998                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
1999                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
2000                 else
2001                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
2002                 break;
2003         }
2004
2005         CHECKGLERROR
2006 #if 0
2007         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
2008         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
2009         r_shadow_drawbuffer = drawbuffer;
2010         r_shadow_readbuffer = readbuffer;
2011 #endif
2012         r_shadow_cullface_front = r_refdef.view.cullface_front;
2013         r_shadow_cullface_back = r_refdef.view.cullface_back;
2014 }
2015
2016 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
2017 {
2018         rsurface.rtlight = rtlight;
2019 }
2020
2021 void R_Shadow_RenderMode_Reset(void)
2022 {
2023         R_Mesh_ResetTextureState();
2024         R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
2025         R_SetViewport(&r_refdef.view.viewport);
2026         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
2027         GL_DepthRange(0, 1);
2028         GL_DepthTest(true);
2029         GL_DepthMask(false);
2030         GL_DepthFunc(GL_LEQUAL);
2031         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2032         r_refdef.view.cullface_front = r_shadow_cullface_front;
2033         r_refdef.view.cullface_back = r_shadow_cullface_back;
2034         GL_CullFace(r_refdef.view.cullface_back);
2035         GL_Color(1, 1, 1, 1);
2036         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2037         GL_BlendFunc(GL_ONE, GL_ZERO);
2038         R_SetupShader_Generic_NoTexture(false, false);
2039         r_shadow_usingshadowmap2d = false;
2040         r_shadow_usingshadowmaportho = false;
2041         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2042 }
2043
2044 void R_Shadow_ClearStencil(void)
2045 {
2046         GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128);
2047         r_refdef.stats.lights_clears++;
2048 }
2049
2050 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
2051 {
2052         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
2053         if (r_shadow_rendermode == mode)
2054                 return;
2055         R_Shadow_RenderMode_Reset();
2056         GL_DepthFunc(GL_LESS);
2057         GL_ColorMask(0, 0, 0, 0);
2058         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2059         GL_CullFace(GL_NONE);
2060         R_SetupShader_DepthOrShadow(false);
2061         r_shadow_rendermode = mode;
2062         switch(mode)
2063         {
2064         default:
2065                 break;
2066         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
2067         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
2068                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, GL_ALWAYS, 128, 255);
2069                 break;
2070         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2071         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
2072                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, GL_ALWAYS, 128, 255);
2073                 break;
2074         }
2075 }
2076
2077 static void R_Shadow_MakeVSDCT(void)
2078 {
2079         // maps to a 2x3 texture rectangle with normalized coordinates
2080         // +-
2081         // XX
2082         // YY
2083         // ZZ
2084         // stores abs(dir.xy), offset.xy/2.5
2085         unsigned char data[4*6] =
2086         {
2087                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2088                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2089                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2090                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2091                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2092                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2093         };
2094         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2095 }
2096
2097 static void R_Shadow_MakeShadowMap(int side, int size)
2098 {
2099         switch (r_shadow_shadowmode)
2100         {
2101         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2102                 if (r_shadow_shadowmap2dtexture) return;
2103                 r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2104                 r_shadow_shadowmap2dcolortexture = NULL;
2105                 switch(vid.renderpath)
2106                 {
2107 #ifdef SUPPORTD3D
2108                 case RENDERPATH_D3D9:
2109                         r_shadow_shadowmap2dcolortexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_BGRA, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2110                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
2111                         break;
2112 #endif
2113                 default:
2114                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL);
2115                         break;
2116                 }
2117                 break;
2118         default:
2119                 return;
2120         }
2121
2122 #ifndef USE_GLES2
2123         // render depth into the fbo, do not render color at all
2124         // validate the fbo now
2125         if (qglDrawBuffer)
2126         {
2127                 int status;
2128                 qglDrawBuffer(GL_NONE);CHECKGLERROR
2129                 qglReadBuffer(GL_NONE);CHECKGLERROR
2130                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
2131                 if (status != GL_FRAMEBUFFER_COMPLETE && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2132                 {
2133                         Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2134                         Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2135                         Cvar_SetValueQuick(&r_shadow_deferred, 0);
2136                 }
2137         }
2138 #endif
2139 }
2140
2141 void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
2142 {
2143         float nearclip, farclip, bias;
2144         r_viewport_t viewport;
2145         int flipped;
2146         GLuint fbo2d = 0;
2147         float clearcolor[4];
2148         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2149         farclip = 1.0f;
2150         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2151         r_shadow_shadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2152         r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2153         r_shadow_shadowmapside = side;
2154         r_shadow_shadowmapsize = size;
2155
2156         r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2157         r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2158         R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2159         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
2160
2161         // complex unrolled cube approach (more flexible)
2162         if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2163                 R_Shadow_MakeVSDCT();
2164         if (!r_shadow_shadowmap2dtexture)
2165                 R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
2166         if (r_shadow_shadowmap2dtexture) fbo2d = r_shadow_fbo2d;
2167         r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
2168         r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
2169         r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2170
2171         R_Mesh_ResetTextureState();
2172         R_Shadow_RenderMode_Reset();
2173         R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
2174         R_SetupShader_DepthOrShadow(true);
2175         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2176         GL_DepthMask(true);
2177         GL_DepthTest(true);
2178
2179 init_done:
2180         R_SetViewport(&viewport);
2181         flipped = (side & 1) ^ (side >> 2);
2182         r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2183         r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2184         switch(vid.renderpath)
2185         {
2186         case RENDERPATH_GL11:
2187         case RENDERPATH_GL13:
2188         case RENDERPATH_GL20:
2189         case RENDERPATH_SOFT:
2190         case RENDERPATH_GLES1:
2191         case RENDERPATH_GLES2:
2192                 GL_CullFace(r_refdef.view.cullface_back);
2193                 // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
2194                 if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
2195                 {
2196                         // get tightest scissor rectangle that encloses all viewports in the clear mask
2197                         int x1 = clear & 0x15 ? 0 : size;
2198                         int x2 = clear & 0x2A ? 2 * size : size;
2199                         int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
2200                         int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
2201                         GL_Scissor(x1, y1, x2 - x1, y2 - y1);
2202                         GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
2203                 }
2204                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2205                 break;
2206         case RENDERPATH_D3D9:
2207         case RENDERPATH_D3D10:
2208         case RENDERPATH_D3D11:
2209                 Vector4Set(clearcolor, 1,1,1,1);
2210                 // completely different meaning than in OpenGL path
2211                 r_shadow_shadowmap_parameters[1] = 0;
2212                 r_shadow_shadowmap_parameters[3] = -bias;
2213                 // we invert the cull mode because we flip the projection matrix
2214                 // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
2215                 GL_CullFace(r_refdef.view.cullface_front);
2216                 // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
2217                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2218                 if (r_shadow_shadowmapsampler)
2219                 {
2220                         GL_ColorMask(0,0,0,0);
2221                         if (clear)
2222                                 GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
2223                 }
2224                 else
2225                 {
2226                         GL_ColorMask(1,1,1,1);
2227                         if (clear)
2228                                 GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
2229                 }
2230                 break;
2231         }
2232 }
2233
2234 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
2235 {
2236         R_Mesh_ResetTextureState();
2237         if (transparent)
2238         {
2239                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2240                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2241                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2242                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2243         }
2244         R_Shadow_RenderMode_Reset();
2245         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2246         if (!transparent)
2247                 GL_DepthFunc(GL_EQUAL);
2248         // do global setup needed for the chosen lighting mode
2249         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2250                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2251         r_shadow_usingshadowmap2d = shadowmapping;
2252         r_shadow_rendermode = r_shadow_lightingrendermode;
2253         // only draw light where this geometry was already rendered AND the
2254         // stencil is 128 (values other than this mean shadow)
2255         if (stenciltest)
2256                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2257         else
2258                 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2259 }
2260
2261 static const unsigned short bboxelements[36] =
2262 {
2263         5, 1, 3, 5, 3, 7,
2264         6, 2, 0, 6, 0, 4,
2265         7, 3, 2, 7, 2, 6,
2266         4, 0, 1, 4, 1, 5,
2267         4, 5, 7, 4, 7, 6,
2268         1, 0, 2, 1, 2, 3,
2269 };
2270
2271 static const float bboxpoints[8][3] =
2272 {
2273         {-1,-1,-1},
2274         { 1,-1,-1},
2275         {-1, 1,-1},
2276         { 1, 1,-1},
2277         {-1,-1, 1},
2278         { 1,-1, 1},
2279         {-1, 1, 1},
2280         { 1, 1, 1},
2281 };
2282
2283 void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadowmapping)
2284 {
2285         int i;
2286         float vertex3f[8*3];
2287         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
2288 // do global setup needed for the chosen lighting mode
2289         R_Shadow_RenderMode_Reset();
2290         r_shadow_rendermode = r_shadow_lightingrendermode;
2291         R_EntityMatrix(&identitymatrix);
2292         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2293         // only draw light where this geometry was already rendered AND the
2294         // stencil is 128 (values other than this mean shadow)
2295         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2296         if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0)
2297                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
2298         else
2299                 R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
2300
2301         r_shadow_usingshadowmap2d = shadowmapping;
2302
2303         // render the lighting
2304         R_SetupShader_DeferredLight(rsurface.rtlight);
2305         for (i = 0;i < 8;i++)
2306                 Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
2307         GL_ColorMask(1,1,1,1);
2308         GL_DepthMask(false);
2309         GL_DepthRange(0, 1);
2310         GL_PolygonOffset(0, 0);
2311         GL_DepthTest(true);
2312         GL_DepthFunc(GL_GREATER);
2313         GL_CullFace(r_refdef.view.cullface_back);
2314         R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL);
2315         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
2316 }
2317
2318 void R_Shadow_UpdateBounceGridTexture(void)
2319 {
2320 #define MAXBOUNCEGRIDPARTICLESPERLIGHT 1048576
2321         dlight_t *light;
2322         int flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
2323         int bouncecount;
2324         int hitsupercontentsmask;
2325         int maxbounce;
2326         int numpixels;
2327         int resolution[3];
2328         int shootparticles;
2329         int shotparticles;
2330         int photoncount;
2331         int tex[3];
2332         trace_t cliptrace;
2333         //trace_t cliptrace2;
2334         //trace_t cliptrace3;
2335         unsigned char *pixel;
2336         unsigned char *pixels;
2337         float *highpixel;
2338         float *highpixels;
2339         unsigned int lightindex;
2340         unsigned int range;
2341         unsigned int range1;
2342         unsigned int range2;
2343         unsigned int seed = (unsigned int)(realtime * 1000.0f);
2344         vec3_t shotcolor;
2345         vec3_t baseshotcolor;
2346         vec3_t surfcolor;
2347         vec3_t clipend;
2348         vec3_t clipstart;
2349         vec3_t clipdiff;
2350         vec3_t ispacing;
2351         vec3_t maxs;
2352         vec3_t mins;
2353         vec3_t size;
2354         vec3_t spacing;
2355         vec3_t lightcolor;
2356         vec3_t steppos;
2357         vec3_t stepdelta;
2358         vec3_t cullmins, cullmaxs;
2359         vec_t radius;
2360         vec_t s;
2361         vec_t lightintensity;
2362         vec_t photonscaling;
2363         vec_t photonresidual;
2364         float m[16];
2365         float texlerp[2][3];
2366         float splatcolor[32];
2367         float pixelweight[8];
2368         float w;
2369         int c[4];
2370         int pixelindex[8];
2371         int corner;
2372         int pixelsperband;
2373         int pixelband;
2374         int pixelbands;
2375         int numsteps;
2376         int step;
2377         int x, y, z;
2378         rtlight_t *rtlight;
2379         r_shadow_bouncegrid_settings_t settings;
2380         qboolean enable = r_shadow_bouncegrid.integer != 0 && r_refdef.scene.worldmodel;
2381         qboolean allowdirectionalshading = false;
2382         switch(vid.renderpath)
2383         {
2384         case RENDERPATH_GL20:
2385                 allowdirectionalshading = true;
2386                 if (!vid.support.ext_texture_3d)
2387                         return;
2388                 break;
2389         case RENDERPATH_GLES2:
2390                 // for performance reasons, do not use directional shading on GLES devices
2391                 if (!vid.support.ext_texture_3d)
2392                         return;
2393                 break;
2394                 // these renderpaths do not currently have the code to display the bouncegrid, so disable it on them...
2395         case RENDERPATH_GL11:
2396         case RENDERPATH_GL13:
2397         case RENDERPATH_GLES1:
2398         case RENDERPATH_SOFT:
2399         case RENDERPATH_D3D9:
2400         case RENDERPATH_D3D10:
2401         case RENDERPATH_D3D11:
2402                 return;
2403         }
2404
2405         r_shadow_bouncegridintensity = r_shadow_bouncegrid_intensity.value;
2406
2407         // see if there are really any lights to render...
2408         if (enable && r_shadow_bouncegrid_static.integer)
2409         {
2410                 enable = false;
2411                 range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
2412                 for (lightindex = 0;lightindex < range;lightindex++)
2413                 {
2414                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2415                         if (!light || !(light->flags & flag))
2416                                 continue;
2417                         rtlight = &light->rtlight;
2418                         // when static, we skip styled lights because they tend to change...
2419                         if (rtlight->style > 0)
2420                                 continue;
2421                         VectorScale(rtlight->color, (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale), lightcolor);
2422                         if (!VectorLength2(lightcolor))
2423                                 continue;
2424                         enable = true;
2425                         break;
2426                 }
2427         }
2428
2429         if (!enable)
2430         {
2431                 if (r_shadow_bouncegridtexture)
2432                 {
2433                         R_FreeTexture(r_shadow_bouncegridtexture);
2434                         r_shadow_bouncegridtexture = NULL;
2435                 }
2436                 if (r_shadow_bouncegridpixels)
2437                         Mem_Free(r_shadow_bouncegridpixels);
2438                 r_shadow_bouncegridpixels = NULL;
2439                 if (r_shadow_bouncegridhighpixels)
2440                         Mem_Free(r_shadow_bouncegridhighpixels);
2441                 r_shadow_bouncegridhighpixels = NULL;
2442                 r_shadow_bouncegridnumpixels = 0;
2443                 r_shadow_bouncegriddirectional = false;
2444                 return;
2445         }
2446
2447         // build up a complete collection of the desired settings, so that memcmp can be used to compare parameters
2448         memset(&settings, 0, sizeof(settings));
2449         settings.staticmode                    = r_shadow_bouncegrid_static.integer != 0;
2450         settings.bounceanglediffuse            = r_shadow_bouncegrid_bounceanglediffuse.integer != 0;
2451         settings.directionalshading            = (r_shadow_bouncegrid_static.integer != 0 ? r_shadow_bouncegrid_static_directionalshading.integer != 0 : r_shadow_bouncegrid_directionalshading.integer != 0) && allowdirectionalshading;
2452         settings.dlightparticlemultiplier      = r_shadow_bouncegrid_dlightparticlemultiplier.value;
2453         settings.hitmodels                     = r_shadow_bouncegrid_hitmodels.integer != 0;
2454         settings.includedirectlighting         = r_shadow_bouncegrid_includedirectlighting.integer != 0 || r_shadow_bouncegrid.integer == 2;
2455         settings.lightradiusscale              = (r_shadow_bouncegrid_static.integer != 0 ? r_shadow_bouncegrid_static_lightradiusscale.value : r_shadow_bouncegrid_lightradiusscale.value);
2456         settings.maxbounce                     = (r_shadow_bouncegrid_static.integer != 0 ? r_shadow_bouncegrid_static_maxbounce.integer : r_shadow_bouncegrid_maxbounce.integer);
2457         settings.particlebounceintensity       = r_shadow_bouncegrid_particlebounceintensity.value;
2458         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);
2459         settings.photons                       = r_shadow_bouncegrid_static.integer ? r_shadow_bouncegrid_static_photons.integer : r_shadow_bouncegrid_photons.integer;
2460         settings.spacing[0]                    = r_shadow_bouncegrid_spacing.value;
2461         settings.spacing[1]                    = r_shadow_bouncegrid_spacing.value;
2462         settings.spacing[2]                    = r_shadow_bouncegrid_spacing.value;
2463         settings.stablerandom                  = r_shadow_bouncegrid_stablerandom.integer;
2464
2465         // bound the values for sanity
2466         settings.photons = bound(1, settings.photons, 1048576);
2467         settings.lightradiusscale = bound(0.0001f, settings.lightradiusscale, 1024.0f);
2468         settings.maxbounce = bound(0, settings.maxbounce, 16);
2469         settings.spacing[0] = bound(1, settings.spacing[0], 512);
2470         settings.spacing[1] = bound(1, settings.spacing[1], 512);
2471         settings.spacing[2] = bound(1, settings.spacing[2], 512);
2472
2473         // get the spacing values
2474         spacing[0] = settings.spacing[0];
2475         spacing[1] = settings.spacing[1];
2476         spacing[2] = settings.spacing[2];
2477         ispacing[0] = 1.0f / spacing[0];
2478         ispacing[1] = 1.0f / spacing[1];
2479         ispacing[2] = 1.0f / spacing[2];
2480
2481         // calculate texture size enclosing entire world bounds at the spacing
2482         VectorMA(r_refdef.scene.worldmodel->normalmins, -2.0f, spacing, mins);
2483         VectorMA(r_refdef.scene.worldmodel->normalmaxs, 2.0f, spacing, maxs);
2484         VectorSubtract(maxs, mins, size);
2485         // now we can calculate the resolution we want
2486         c[0] = (int)floor(size[0] / spacing[0] + 0.5f);
2487         c[1] = (int)floor(size[1] / spacing[1] + 0.5f);
2488         c[2] = (int)floor(size[2] / spacing[2] + 0.5f);
2489         // figure out the exact texture size (honoring power of 2 if required)
2490         c[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
2491         c[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
2492         c[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
2493         if (vid.support.arb_texture_non_power_of_two)
2494         {
2495                 resolution[0] = c[0];
2496                 resolution[1] = c[1];
2497                 resolution[2] = c[2];
2498         }
2499         else
2500         {
2501                 for (resolution[0] = 4;resolution[0] < c[0];resolution[0]*=2) ;
2502                 for (resolution[1] = 4;resolution[1] < c[1];resolution[1]*=2) ;
2503                 for (resolution[2] = 4;resolution[2] < c[2];resolution[2]*=2) ;
2504         }
2505         size[0] = spacing[0] * resolution[0];
2506         size[1] = spacing[1] * resolution[1];
2507         size[2] = spacing[2] * resolution[2];
2508
2509         // if dynamic we may or may not want to use the world bounds
2510         // if the dynamic size is smaller than the world bounds, use it instead
2511         if (!settings.staticmode && (r_shadow_bouncegrid_x.integer * r_shadow_bouncegrid_y.integer * r_shadow_bouncegrid_z.integer < resolution[0] * resolution[1] * resolution[2]))
2512         {
2513                 // we know the resolution we want
2514                 c[0] = r_shadow_bouncegrid_x.integer;
2515                 c[1] = r_shadow_bouncegrid_y.integer;
2516                 c[2] = r_shadow_bouncegrid_z.integer;
2517                 // now we can calculate the texture size (power of 2 if required)
2518                 c[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
2519                 c[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
2520                 c[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
2521                 if (vid.support.arb_texture_non_power_of_two)
2522                 {
2523                         resolution[0] = c[0];
2524                         resolution[1] = c[1];
2525                         resolution[2] = c[2];
2526                 }
2527                 else
2528                 {
2529                         for (resolution[0] = 4;resolution[0] < c[0];resolution[0]*=2) ;
2530                         for (resolution[1] = 4;resolution[1] < c[1];resolution[1]*=2) ;
2531                         for (resolution[2] = 4;resolution[2] < c[2];resolution[2]*=2) ;
2532                 }
2533                 size[0] = spacing[0] * resolution[0];
2534                 size[1] = spacing[1] * resolution[1];
2535                 size[2] = spacing[2] * resolution[2];
2536                 // center the rendering on the view
2537                 mins[0] = floor(r_refdef.view.origin[0] * ispacing[0] + 0.5f) * spacing[0] - 0.5f * size[0];
2538                 mins[1] = floor(r_refdef.view.origin[1] * ispacing[1] + 0.5f) * spacing[1] - 0.5f * size[1];
2539                 mins[2] = floor(r_refdef.view.origin[2] * ispacing[2] + 0.5f) * spacing[2] - 0.5f * size[2];
2540         }
2541
2542         // recalculate the maxs in case the resolution was not satisfactory
2543         VectorAdd(mins, size, maxs);
2544
2545         // if all the settings seem identical to the previous update, return
2546         if (r_shadow_bouncegridtexture && (settings.staticmode || realtime < r_shadow_bouncegridtime + r_shadow_bouncegrid_updateinterval.value) && !memcmp(&r_shadow_bouncegridsettings, &settings, sizeof(settings)))
2547                 return;
2548
2549         // store the new settings
2550         r_shadow_bouncegridsettings = settings;
2551
2552         pixelbands = settings.directionalshading ? 8 : 1;
2553         pixelsperband = resolution[0]*resolution[1]*resolution[2];
2554         numpixels = pixelsperband*pixelbands;
2555
2556         // we're going to update the bouncegrid, update the matrix...
2557         memset(m, 0, sizeof(m));
2558         m[0] = 1.0f / size[0];
2559         m[3] = -mins[0] * m[0];
2560         m[5] = 1.0f / size[1];
2561         m[7] = -mins[1] * m[5];
2562         m[10] = 1.0f / size[2];
2563         m[11] = -mins[2] * m[10];
2564         m[15] = 1.0f;
2565         Matrix4x4_FromArrayFloatD3D(&r_shadow_bouncegridmatrix, m);
2566         // reallocate pixels for this update if needed...
2567         if (r_shadow_bouncegridnumpixels != numpixels || !r_shadow_bouncegridpixels || !r_shadow_bouncegridhighpixels)
2568         {
2569                 if (r_shadow_bouncegridtexture)
2570                 {
2571                         R_FreeTexture(r_shadow_bouncegridtexture);
2572                         r_shadow_bouncegridtexture = NULL;
2573                 }
2574                 r_shadow_bouncegridpixels = (unsigned char *)Mem_Realloc(r_main_mempool, r_shadow_bouncegridpixels, numpixels * sizeof(unsigned char[4]));
2575                 r_shadow_bouncegridhighpixels = (float *)Mem_Realloc(r_main_mempool, r_shadow_bouncegridhighpixels, numpixels * sizeof(float[4]));
2576         }
2577         r_shadow_bouncegridnumpixels = numpixels;
2578         pixels = r_shadow_bouncegridpixels;
2579         highpixels = r_shadow_bouncegridhighpixels;
2580         x = pixelsperband*4;
2581         for (pixelband = 0;pixelband < pixelbands;pixelband++)
2582         {
2583                 if (pixelband == 1)
2584                         memset(pixels + pixelband * x, 128, x);
2585                 else
2586                         memset(pixels + pixelband * x, 0, x);
2587         }
2588         memset(highpixels, 0, numpixels * sizeof(float[4]));
2589         // figure out what we want to interact with
2590         if (settings.hitmodels)
2591                 hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;// | SUPERCONTENTS_LIQUIDSMASK;
2592         else
2593                 hitsupercontentsmask = SUPERCONTENTS_SOLID;// | SUPERCONTENTS_LIQUIDSMASK;
2594         maxbounce = settings.maxbounce;
2595         // clear variables that produce warnings otherwise
2596         memset(splatcolor, 0, sizeof(splatcolor));
2597         // iterate world rtlights
2598         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
2599         range1 = settings.staticmode ? 0 : r_refdef.scene.numlights;
2600         range2 = range + range1;
2601         photoncount = 0;
2602         for (lightindex = 0;lightindex < range2;lightindex++)
2603         {
2604                 if (lightindex < range)
2605                 {
2606                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2607                         if (!light)
2608                                 continue;
2609                         rtlight = &light->rtlight;
2610                         VectorClear(rtlight->photoncolor);
2611                         rtlight->photons = 0;
2612                         if (!(light->flags & flag))
2613                                 continue;
2614                         if (settings.staticmode)
2615                         {
2616                                 // when static, we skip styled lights because they tend to change...
2617                                 if (rtlight->style > 0 && r_shadow_bouncegrid.integer != 2)
2618                                         continue;
2619                         }
2620                 }
2621                 else
2622                 {
2623                         rtlight = r_refdef.scene.lights[lightindex - range];
2624                         VectorClear(rtlight->photoncolor);
2625                         rtlight->photons = 0;
2626                 }
2627                 // draw only visible lights (major speedup)
2628                 radius = rtlight->radius * settings.lightradiusscale;
2629                 cullmins[0] = rtlight->shadoworigin[0] - radius;
2630                 cullmins[1] = rtlight->shadoworigin[1] - radius;
2631                 cullmins[2] = rtlight->shadoworigin[2] - radius;
2632                 cullmaxs[0] = rtlight->shadoworigin[0] + radius;
2633                 cullmaxs[1] = rtlight->shadoworigin[1] + radius;
2634                 cullmaxs[2] = rtlight->shadoworigin[2] + radius;
2635                 if (R_CullBox(cullmins, cullmaxs))
2636                         continue;
2637                 if (r_refdef.scene.worldmodel
2638                  && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs
2639                  && !r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, cullmins, cullmaxs))
2640                         continue;
2641                 w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2642                 if (w * VectorLength2(rtlight->color) == 0.0f)
2643                         continue;
2644                 w *= (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
2645                 VectorScale(rtlight->color, w, rtlight->photoncolor);
2646                 //if (!VectorLength2(rtlight->photoncolor))
2647                 //      continue;
2648                 // shoot particles from this light
2649                 // use a calculation for the number of particles that will not
2650                 // vary with lightstyle, otherwise we get randomized particle
2651                 // distribution, the seeded random is only consistent for a
2652                 // consistent number of particles on this light...
2653                 s = rtlight->radius;
2654                 lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2655                 if (lightindex >= range)
2656                         lightintensity *= settings.dlightparticlemultiplier;
2657                 rtlight->photons = max(0.0f, lightintensity * s * s);
2658                 photoncount += rtlight->photons;
2659         }
2660         photonscaling = (float)settings.photons / max(1, photoncount);
2661         photonresidual = 0.0f;
2662         for (lightindex = 0;lightindex < range2;lightindex++)
2663         {
2664                 if (lightindex < range)
2665                 {
2666                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
2667                         if (!light)
2668                                 continue;
2669                         rtlight = &light->rtlight;
2670                 }
2671                 else
2672                         rtlight = r_refdef.scene.lights[lightindex - range];
2673                 // skip a light with no photons
2674                 if (rtlight->photons == 0.0f)
2675                         continue;
2676                 // skip a light with no photon color)
2677                 if (VectorLength2(rtlight->photoncolor) == 0.0f)
2678                         continue;
2679                 photonresidual += rtlight->photons * photonscaling;
2680                 shootparticles = (int)bound(0, photonresidual, MAXBOUNCEGRIDPARTICLESPERLIGHT);
2681                 if (!shootparticles)
2682                         continue;
2683                 photonresidual -= shootparticles;
2684                 radius = rtlight->radius * settings.lightradiusscale;
2685                 s = settings.particleintensity / shootparticles;
2686                 VectorScale(rtlight->photoncolor, s, baseshotcolor);
2687                 r_refdef.stats.bouncegrid_lights++;
2688                 r_refdef.stats.bouncegrid_particles += shootparticles;
2689                 for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
2690                 {
2691                         if (settings.stablerandom > 0)
2692                                 seed = lightindex * 11937 + shotparticles;
2693                         VectorCopy(baseshotcolor, shotcolor);
2694                         VectorCopy(rtlight->shadoworigin, clipstart);
2695                         if (settings.stablerandom < 0)
2696                                 VectorRandom(clipend);
2697                         else
2698                                 VectorCheeseRandom(clipend);
2699                         VectorMA(clipstart, radius, clipend, clipend);
2700                         for (bouncecount = 0;;bouncecount++)
2701                         {
2702                                 r_refdef.stats.bouncegrid_traces++;
2703                                 //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
2704                                 //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
2705                                 //if (settings.staticmode)
2706                                 //      Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, true);
2707                                 //else
2708                                         cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true);
2709                                 if (bouncecount > 0 || settings.includedirectlighting)
2710                                 {
2711                                         // calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
2712                                         // accumulate average shotcolor
2713                                         w = VectorLength(shotcolor);
2714                                         splatcolor[ 0] = shotcolor[0];
2715                                         splatcolor[ 1] = shotcolor[1];
2716                                         splatcolor[ 2] = shotcolor[2];
2717                                         splatcolor[ 3] = 0.0f;
2718                                         if (pixelbands > 1)
2719                                         {
2720                                                 VectorSubtract(clipstart, cliptrace.endpos, clipdiff);
2721                                                 VectorNormalize(clipdiff);
2722                                                 // store bentnormal in case the shader has a use for it
2723                                                 splatcolor[ 4] = clipdiff[0] * w;
2724                                                 splatcolor[ 5] = clipdiff[1] * w;
2725                                                 splatcolor[ 6] = clipdiff[2] * w;
2726                                                 splatcolor[ 7] = w;
2727                                                 // accumulate directional contributions (+X, +Y, +Z, -X, -Y, -Z)
2728                                                 splatcolor[ 8] = shotcolor[0] * max(0.0f, clipdiff[0]);
2729                                                 splatcolor[ 9] = shotcolor[0] * max(0.0f, clipdiff[1]);
2730                                                 splatcolor[10] = shotcolor[0] * max(0.0f, clipdiff[2]);
2731                                                 splatcolor[11] = 0.0f;
2732                                                 splatcolor[12] = shotcolor[1] * max(0.0f, clipdiff[0]);
2733                                                 splatcolor[13] = shotcolor[1] * max(0.0f, clipdiff[1]);
2734                                                 splatcolor[14] = shotcolor[1] * max(0.0f, clipdiff[2]);
2735                                                 splatcolor[15] = 0.0f;
2736                                                 splatcolor[16] = shotcolor[2] * max(0.0f, clipdiff[0]);
2737                                                 splatcolor[17] = shotcolor[2] * max(0.0f, clipdiff[1]);
2738                                                 splatcolor[18] = shotcolor[2] * max(0.0f, clipdiff[2]);
2739                                                 splatcolor[19] = 0.0f;
2740                                                 splatcolor[20] = shotcolor[0] * max(0.0f, -clipdiff[0]);
2741                                                 splatcolor[21] = shotcolor[0] * max(0.0f, -clipdiff[1]);
2742                                                 splatcolor[22] = shotcolor[0] * max(0.0f, -clipdiff[2]);
2743                                                 splatcolor[23] = 0.0f;
2744                                                 splatcolor[24] = shotcolor[1] * max(0.0f, -clipdiff[0]);
2745                                                 splatcolor[25] = shotcolor[1] * max(0.0f, -clipdiff[1]);
2746                                                 splatcolor[26] = shotcolor[1] * max(0.0f, -clipdiff[2]);
2747                                                 splatcolor[27] = 0.0f;
2748                                                 splatcolor[28] = shotcolor[2] * max(0.0f, -clipdiff[0]);
2749                                                 splatcolor[29] = shotcolor[2] * max(0.0f, -clipdiff[1]);
2750                                                 splatcolor[30] = shotcolor[2] * max(0.0f, -clipdiff[2]);
2751                                                 splatcolor[31] = 0.0f;
2752                                         }
2753                                         // calculate the number of steps we need to traverse this distance
2754                                         VectorSubtract(cliptrace.endpos, clipstart, stepdelta);
2755                                         numsteps = (int)(VectorLength(stepdelta) * ispacing[0]);
2756                                         numsteps = bound(1, numsteps, 1024);
2757                                         w = 1.0f / numsteps;
2758                                         VectorScale(stepdelta, w, stepdelta);
2759                                         VectorMA(clipstart, 0.5f, stepdelta, steppos);
2760                                         for (step = 0;step < numsteps;step++)
2761                                         {
2762                                                 r_refdef.stats.bouncegrid_splats++;
2763                                                 // figure out which texture pixel this is in
2764                                                 texlerp[1][0] = ((steppos[0] - mins[0]) * ispacing[0]) - 0.5f;
2765                                                 texlerp[1][1] = ((steppos[1] - mins[1]) * ispacing[1]) - 0.5f;
2766                                                 texlerp[1][2] = ((steppos[2] - mins[2]) * ispacing[2]) - 0.5f;
2767                                                 tex[0] = (int)floor(texlerp[1][0]);
2768                                                 tex[1] = (int)floor(texlerp[1][1]);
2769                                                 tex[2] = (int)floor(texlerp[1][2]);
2770                                                 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)
2771                                                 {
2772                                                         // it is within bounds...  do the real work now
2773                                                         // calculate the lerp factors
2774                                                         texlerp[1][0] -= tex[0];
2775                                                         texlerp[1][1] -= tex[1];
2776                                                         texlerp[1][2] -= tex[2];
2777                                                         texlerp[0][0] = 1.0f - texlerp[1][0];
2778                                                         texlerp[0][1] = 1.0f - texlerp[1][1];
2779                                                         texlerp[0][2] = 1.0f - texlerp[1][2];
2780                                                         // calculate individual pixel indexes and weights
2781                                                         pixelindex[0] = (((tex[2]  )*resolution[1]+tex[1]  )*resolution[0]+tex[0]  );pixelweight[0] = (texlerp[0][0]*texlerp[0][1]*texlerp[0][2]);
2782                                                         pixelindex[1] = (((tex[2]  )*resolution[1]+tex[1]  )*resolution[0]+tex[0]+1);pixelweight[1] = (texlerp[1][0]*texlerp[0][1]*texlerp[0][2]);
2783                                                         pixelindex[2] = (((tex[2]  )*resolution[1]+tex[1]+1)*resolution[0]+tex[0]  );pixelweight[2] = (texlerp[0][0]*texlerp[1][1]*texlerp[0][2]);
2784                                                         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]);
2785                                                         pixelindex[4] = (((tex[2]+1)*resolution[1]+tex[1]  )*resolution[0]+tex[0]  );pixelweight[4] = (texlerp[0][0]*texlerp[0][1]*texlerp[1][2]);
2786                                                         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]);
2787                                                         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]);
2788                                                         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]);
2789                                                         // update the 8 pixels...
2790                                                         for (pixelband = 0;pixelband < pixelbands;pixelband++)
2791                                                         {
2792                                                                 for (corner = 0;corner < 8;corner++)
2793                                                                 {
2794                                                                         // calculate address for pixel
2795                                                                         w = pixelweight[corner];
2796                                                                         pixel = pixels + 4 * pixelindex[corner] + pixelband * pixelsperband * 4;
2797                                                                         highpixel = highpixels + 4 * pixelindex[corner] + pixelband * pixelsperband * 4;
2798                                                                         // add to the high precision pixel color
2799                                                                         highpixel[0] += (splatcolor[pixelband*4+0]*w);
2800                                                                         highpixel[1] += (splatcolor[pixelband*4+1]*w);
2801                                                                         highpixel[2] += (splatcolor[pixelband*4+2]*w);
2802                                                                         highpixel[3] += (splatcolor[pixelband*4+3]*w);
2803                                                                         // flag the low precision pixel as needing to be updated
2804                                                                         pixel[3] = 255;
2805                                                                         // advance to next band of coefficients
2806                                                                         //pixel += pixelsperband*4;
2807                                                                         //highpixel += pixelsperband*4;
2808                                                                 }
2809                                                         }
2810                                                 }
2811                                                 VectorAdd(steppos, stepdelta, steppos);
2812                                         }
2813                                 }
2814                                 if (cliptrace.fraction >= 1.0f)
2815                                         break;
2816                                 r_refdef.stats.bouncegrid_hits++;
2817                                 if (bouncecount >= maxbounce)
2818                                         break;
2819                                 // scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
2820                                 // also clamp the resulting color to never add energy, even if the user requests extreme values
2821                                 if (cliptrace.hittexture && cliptrace.hittexture->currentskinframe)
2822                                         VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, surfcolor);
2823                                 else
2824                                         VectorSet(surfcolor, 0.5f, 0.5f, 0.5f);
2825                                 VectorScale(surfcolor, settings.particlebounceintensity, surfcolor);
2826                                 surfcolor[0] = min(surfcolor[0], 1.0f);
2827                                 surfcolor[1] = min(surfcolor[1], 1.0f);
2828                                 surfcolor[2] = min(surfcolor[2], 1.0f);
2829                                 VectorMultiply(shotcolor, surfcolor, shotcolor);
2830                                 if (VectorLength2(baseshotcolor) == 0.0f)
2831                                         break;
2832                                 r_refdef.stats.bouncegrid_bounces++;
2833                                 if (settings.bounceanglediffuse)
2834                                 {
2835                                         // random direction, primarily along plane normal
2836                                         s = VectorDistance(cliptrace.endpos, clipend);
2837                                         if (settings.stablerandom < 0)
2838                                                 VectorRandom(clipend);
2839                                         else
2840                                                 VectorCheeseRandom(clipend);
2841                                         VectorMA(cliptrace.plane.normal, 0.95f, clipend, clipend);
2842                                         VectorNormalize(clipend);
2843                                         VectorScale(clipend, s, clipend);
2844                                 }
2845                                 else
2846                                 {
2847                                         // reflect the remaining portion of the line across plane normal
2848                                         VectorSubtract(clipend, cliptrace.endpos, clipdiff);
2849                                         VectorReflect(clipdiff, 1.0, cliptrace.plane.normal, clipend);
2850                                 }
2851                                 // calculate the new line start and end
2852                                 VectorCopy(cliptrace.endpos, clipstart);
2853                                 VectorAdd(clipstart, clipend, clipend);
2854                         }
2855                 }
2856         }
2857         // generate pixels array from highpixels array
2858         // skip first and last columns, rows, and layers as these are blank
2859         // the pixel[3] value was written above, so we can use it to detect only pixels that need to be calculated
2860         for (pixelband = 0;pixelband < pixelbands;pixelband++)
2861         {
2862                 for (z = 1;z < resolution[2]-1;z++)
2863                 {
2864                         for (y = 1;y < resolution[1]-1;y++)
2865                         {
2866                                 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)
2867                                 {
2868                                         // only convert pixels that were hit by photons
2869                                         if (pixel[3] == 255)
2870                                         {
2871                                                 // normalize the bentnormal...
2872                                                 if (pixelband == 1)
2873                                                 {
2874                                                         VectorNormalize(highpixel);
2875                                                         c[0] = (int)(highpixel[0]*128.0f+128.0f);
2876                                                         c[1] = (int)(highpixel[1]*128.0f+128.0f);
2877                                                         c[2] = (int)(highpixel[2]*128.0f+128.0f);
2878                                                         c[3] = (int)(highpixel[3]*128.0f+128.0f);
2879                                                 }
2880                                                 else
2881                                                 {
2882                                                         c[0] = (int)(highpixel[0]*256.0f);
2883                                                         c[1] = (int)(highpixel[1]*256.0f);
2884                                                         c[2] = (int)(highpixel[2]*256.0f);
2885                                                         c[3] = (int)(highpixel[3]*256.0f);
2886                                                 }
2887                                                 pixel[2] = (unsigned char)bound(0, c[0], 255);
2888                                                 pixel[1] = (unsigned char)bound(0, c[1], 255);
2889                                                 pixel[0] = (unsigned char)bound(0, c[2], 255);
2890                                                 pixel[3] = (unsigned char)bound(0, c[3], 255);
2891                                         }
2892                                 }
2893                         }
2894                 }
2895         }
2896         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)
2897                 R_UpdateTexture(r_shadow_bouncegridtexture, pixels, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
2898         else
2899         {
2900                 VectorCopy(resolution, r_shadow_bouncegridresolution);
2901                 r_shadow_bouncegriddirectional = settings.directionalshading;
2902                 if (r_shadow_bouncegridtexture)
2903                         R_FreeTexture(r_shadow_bouncegridtexture);
2904                 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);
2905         }
2906         r_shadow_bouncegridtime = realtime;
2907 }
2908
2909 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
2910 {
2911         R_Shadow_RenderMode_Reset();
2912         GL_BlendFunc(GL_ONE, GL_ONE);
2913         GL_DepthRange(0, 1);
2914         GL_DepthTest(r_showshadowvolumes.integer < 2);
2915         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
2916         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2917         GL_CullFace(GL_NONE);
2918         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
2919 }
2920
2921 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
2922 {
2923         R_Shadow_RenderMode_Reset();
2924         GL_BlendFunc(GL_ONE, GL_ONE);
2925         GL_DepthRange(0, 1);
2926         GL_DepthTest(r_showlighting.integer < 2);
2927         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2928         if (!transparent)
2929                 GL_DepthFunc(GL_EQUAL);
2930         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2931         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2932 }
2933
2934 void R_Shadow_RenderMode_End(void)
2935 {
2936         R_Shadow_RenderMode_Reset();
2937         R_Shadow_RenderMode_ActiveLight(NULL);
2938         GL_DepthMask(true);
2939         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2940         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2941 }
2942
2943 int bboxedges[12][2] =
2944 {
2945         // top
2946         {0, 1}, // +X
2947         {0, 2}, // +Y
2948         {1, 3}, // Y, +X
2949         {2, 3}, // X, +Y
2950         // bottom
2951         {4, 5}, // +X
2952         {4, 6}, // +Y
2953         {5, 7}, // Y, +X
2954         {6, 7}, // X, +Y
2955         // verticals
2956         {0, 4}, // +Z
2957         {1, 5}, // X, +Z
2958         {2, 6}, // Y, +Z
2959         {3, 7}, // XY, +Z
2960 };
2961
2962 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2963 {
2964         if (!r_shadow_scissor.integer || r_shadow_usingdeferredprepass || r_trippy.integer)
2965         {
2966                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2967                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2968                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2969                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2970                 return false;
2971         }
2972         if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
2973                 return true; // invisible
2974         if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
2975         || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
2976         || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
2977         || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
2978                 r_refdef.stats.lights_scissored++;
2979         return false;
2980 }
2981
2982 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor)
2983 {
2984         int i;
2985         const float *vertex3f;
2986         const float *normal3f;
2987         float *color4f;
2988         float dist, dot, distintensity, shadeintensity, v[3], n[3];
2989         switch (r_shadow_rendermode)
2990         {
2991         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2992         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2993                 if (VectorLength2(diffusecolor) > 0)
2994                 {
2995                         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)
2996                         {
2997                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2998                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2999                                 if ((dot = DotProduct(n, v)) < 0)
3000                                 {
3001                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3002                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
3003                                 }
3004                                 else
3005                                         VectorCopy(ambientcolor, color4f);
3006                                 if (r_refdef.fogenabled)
3007                                 {
3008                                         float f;
3009                                         f = RSurf_FogVertex(vertex3f);
3010                                         VectorScale(color4f, f, color4f);
3011                                 }
3012                                 color4f[3] = 1;
3013                         }
3014                 }
3015                 else
3016                 {
3017                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3018                         {
3019                                 VectorCopy(ambientcolor, color4f);
3020                                 if (r_refdef.fogenabled)
3021                                 {
3022                                         float f;
3023                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3024                                         f = RSurf_FogVertex(vertex3f);
3025                                         VectorScale(color4f + 4*i, f, color4f);
3026                                 }
3027                                 color4f[3] = 1;
3028                         }
3029                 }
3030                 break;
3031         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3032                 if (VectorLength2(diffusecolor) > 0)
3033                 {
3034                         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)
3035                         {
3036                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3037                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3038                                 {
3039                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3040                                         if ((dot = DotProduct(n, v)) < 0)
3041                                         {
3042                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3043                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3044                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3045                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3046                                         }
3047                                         else
3048                                         {
3049                                                 color4f[0] = ambientcolor[0] * distintensity;
3050                                                 color4f[1] = ambientcolor[1] * distintensity;
3051                                                 color4f[2] = ambientcolor[2] * distintensity;
3052                                         }
3053                                         if (r_refdef.fogenabled)
3054                                         {
3055                                                 float f;
3056                                                 f = RSurf_FogVertex(vertex3f);
3057                                                 VectorScale(color4f, f, color4f);
3058                                         }
3059                                 }
3060                                 else
3061                                         VectorClear(color4f);
3062                                 color4f[3] = 1;
3063                         }
3064                 }
3065                 else
3066                 {
3067                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3068                         {
3069                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3070                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3071                                 {
3072                                         color4f[0] = ambientcolor[0] * distintensity;
3073                                         color4f[1] = ambientcolor[1] * distintensity;
3074                                         color4f[2] = ambientcolor[2] * distintensity;
3075                                         if (r_refdef.fogenabled)
3076                                         {
3077                                                 float f;
3078                                                 f = RSurf_FogVertex(vertex3f);
3079                                                 VectorScale(color4f, f, color4f);
3080                                         }
3081                                 }
3082                                 else
3083                                         VectorClear(color4f);
3084                                 color4f[3] = 1;
3085                         }
3086                 }
3087                 break;
3088         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3089                 if (VectorLength2(diffusecolor) > 0)
3090                 {
3091                         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)
3092                         {
3093                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3094                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3095                                 {
3096                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3097                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
3098                                         if ((dot = DotProduct(n, v)) < 0)
3099                                         {
3100                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
3101                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
3102                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
3103                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
3104                                         }
3105                                         else
3106                                         {
3107                                                 color4f[0] = ambientcolor[0] * distintensity;
3108                                                 color4f[1] = ambientcolor[1] * distintensity;
3109                                                 color4f[2] = ambientcolor[2] * distintensity;
3110                                         }
3111                                         if (r_refdef.fogenabled)
3112                                         {
3113                                                 float f;
3114                                                 f = RSurf_FogVertex(vertex3f);
3115                                                 VectorScale(color4f, f, color4f);
3116                                         }
3117                                 }
3118                                 else
3119                                         VectorClear(color4f);
3120                                 color4f[3] = 1;
3121                         }
3122                 }
3123                 else
3124                 {
3125                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
3126                         {
3127                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
3128                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
3129                                 {
3130                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
3131                                         color4f[0] = ambientcolor[0] * distintensity;
3132                                         color4f[1] = ambientcolor[1] * distintensity;
3133                                         color4f[2] = ambientcolor[2] * distintensity;
3134                                         if (r_refdef.fogenabled)
3135                                         {
3136                                                 float f;
3137                                                 f = RSurf_FogVertex(vertex3f);
3138                                                 VectorScale(color4f, f, color4f);
3139                                         }
3140                                 }
3141                                 else
3142                                         VectorClear(color4f);
3143                                 color4f[3] = 1;
3144                         }
3145                 }
3146                 break;
3147         default:
3148                 break;
3149         }
3150 }
3151
3152 static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
3153 {
3154         // used to display how many times a surface is lit for level design purposes
3155         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3156         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
3157         RSurf_DrawBatch();
3158 }
3159
3160 static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
3161 {
3162         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
3163         R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
3164         RSurf_DrawBatch();
3165 }
3166
3167 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
3168 {
3169         int renders;
3170         int i;
3171         int stop;
3172         int newfirstvertex;
3173         int newlastvertex;
3174         int newnumtriangles;
3175         int *newe;
3176         const int *e;
3177         float *c;
3178         int maxtriangles = 4096;
3179         static int newelements[4096*3];
3180         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
3181         for (renders = 0;renders < 4;renders++)
3182         {
3183                 stop = true;
3184                 newfirstvertex = 0;
3185                 newlastvertex = 0;
3186                 newnumtriangles = 0;
3187                 newe = newelements;
3188                 // due to low fillrate on the cards this vertex lighting path is
3189                 // designed for, we manually cull all triangles that do not
3190                 // contain a lit vertex
3191                 // this builds batches of triangles from multiple surfaces and
3192                 // renders them at once
3193                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
3194                 {
3195                         if (VectorLength2(rsurface.passcolor4f + e[0] * 4) + VectorLength2(rsurface.passcolor4f + e[1] * 4) + VectorLength2(rsurface.passcolor4f + e[2] * 4) >= 0.01)
3196                         {
3197                                 if (newnumtriangles)
3198                                 {
3199                                         newfirstvertex = min(newfirstvertex, e[0]);
3200                                         newlastvertex  = max(newlastvertex, e[0]);
3201                                 }
3202                                 else
3203                                 {
3204                                         newfirstvertex = e[0];
3205                                         newlastvertex = e[0];
3206                                 }
3207                                 newfirstvertex = min(newfirstvertex, e[1]);
3208                                 newlastvertex  = max(newlastvertex, e[1]);
3209                                 newfirstvertex = min(newfirstvertex, e[2]);
3210                                 newlastvertex  = max(newlastvertex, e[2]);
3211                                 newe[0] = e[0];
3212                                 newe[1] = e[1];
3213                                 newe[2] = e[2];
3214                                 newnumtriangles++;
3215                                 newe += 3;
3216                                 if (newnumtriangles >= maxtriangles)
3217                                 {
3218                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3219                                         newnumtriangles = 0;
3220                                         newe = newelements;
3221                                         stop = false;
3222                                 }
3223                         }
3224                 }
3225                 if (newnumtriangles >= 1)
3226                 {
3227                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
3228                         stop = false;
3229                 }
3230                 // if we couldn't find any lit triangles, exit early
3231                 if (stop)
3232                         break;
3233                 // now reduce the intensity for the next overbright pass
3234                 // we have to clamp to 0 here incase the drivers have improper
3235                 // handling of negative colors
3236                 // (some old drivers even have improper handling of >1 color)
3237                 stop = true;
3238                 for (i = 0, c = rsurface.passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
3239                 {
3240                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
3241                         {
3242                                 c[0] = max(0, c[0] - 1);
3243                                 c[1] = max(0, c[1] - 1);
3244                                 c[2] = max(0, c[2] - 1);
3245                                 stop = false;
3246                         }
3247                         else
3248                                 VectorClear(c);
3249                 }
3250                 // another check...
3251                 if (stop)
3252                         break;
3253         }
3254 }
3255
3256 static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale)
3257 {
3258         // OpenGL 1.1 path (anything)
3259         float ambientcolorbase[3], diffusecolorbase[3];
3260         float ambientcolorpants[3], diffusecolorpants[3];
3261         float ambientcolorshirt[3], diffusecolorshirt[3];
3262         const float *surfacecolor = rsurface.texture->dlightcolor;
3263         const float *surfacepants = rsurface.colormap_pantscolor;
3264         const float *surfaceshirt = rsurface.colormap_shirtcolor;
3265         rtexture_t *basetexture = rsurface.texture->basetexture;
3266         rtexture_t *pantstexture = rsurface.texture->pantstexture;
3267         rtexture_t *shirttexture = rsurface.texture->shirttexture;
3268         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
3269         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
3270         ambientscale *= 2 * r_refdef.view.colorscale;
3271         diffusescale *= 2 * r_refdef.view.colorscale;
3272         ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
3273         diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
3274         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
3275         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
3276         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
3277         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
3278         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
3279         rsurface.passcolor4f = (float *)R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4]));
3280         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3281         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
3282         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
3283         R_Mesh_TexBind(0, basetexture);
3284         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
3285         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
3286         switch(r_shadow_rendermode)
3287         {
3288         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3289                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
3290                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
3291                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
3292                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3293                 break;
3294         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3295                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
3296                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
3297                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
3298                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3299                 // fall through
3300         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3301                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
3302                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
3303                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
3304                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
3305                 break;
3306         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3307                 break;
3308         default:
3309                 break;
3310         }
3311         //R_Mesh_TexBind(0, basetexture);
3312         R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase);
3313         if (dopants)
3314         {
3315                 R_Mesh_TexBind(0, pantstexture);
3316                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants);
3317         }
3318         if (doshirt)
3319         {
3320                 R_Mesh_TexBind(0, shirttexture);
3321                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt);
3322         }
3323 }
3324
3325 extern cvar_t gl_lightmaps;
3326 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
3327 {
3328         float ambientscale, diffusescale, specularscale;
3329         qboolean negated;
3330         float lightcolor[3];
3331         VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
3332         ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient;
3333         diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient);
3334         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
3335         if (!r_shadow_usenormalmap.integer)
3336         {
3337                 ambientscale += 1.0f * diffusescale;
3338                 diffusescale = 0;
3339                 specularscale = 0;
3340         }
3341         if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
3342                 return;
3343         negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
3344         if(negated)
3345         {
3346                 VectorNegate(lightcolor, lightcolor);
3347                 GL_BlendEquationSubtract(true);
3348         }
3349         RSurf_SetupDepthAndCulling();
3350         switch (r_shadow_rendermode)
3351         {
3352         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
3353                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
3354                 R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
3355                 break;
3356         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
3357                 R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale);
3358                 break;
3359         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
3360         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
3361         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
3362         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
3363                 R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale);
3364                 break;
3365         default:
3366                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
3367                 break;
3368         }
3369         if(negated)
3370                 GL_BlendEquationSubtract(false);
3371 }
3372
3373 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)
3374 {
3375         matrix4x4_t tempmatrix = *matrix;
3376         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
3377
3378         // if this light has been compiled before, free the associated data
3379         R_RTLight_Uncompile(rtlight);
3380
3381         // clear it completely to avoid any lingering data
3382         memset(rtlight, 0, sizeof(*rtlight));
3383
3384         // copy the properties
3385         rtlight->matrix_lighttoworld = tempmatrix;
3386         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
3387         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
3388         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
3389         VectorCopy(color, rtlight->color);
3390         rtlight->cubemapname[0] = 0;
3391         if (cubemapname && cubemapname[0])
3392                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
3393         rtlight->shadow = shadow;
3394         rtlight->corona = corona;
3395         rtlight->style = style;
3396         rtlight->isstatic = isstatic;
3397         rtlight->coronasizescale = coronasizescale;
3398         rtlight->ambientscale = ambientscale;
3399         rtlight->diffusescale = diffusescale;
3400         rtlight->specularscale = specularscale;
3401         rtlight->flags = flags;
3402