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