229ac9e87fedebb991a2db6364086059121bf340
[divverent/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
143 extern void R_Shadow_EditLights_Init(void);
144
145 typedef enum r_shadow_rendermode_e
146 {
147         R_SHADOW_RENDERMODE_NONE,
148         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
149         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
150         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
151         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
152         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
153         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
154         R_SHADOW_RENDERMODE_LIGHT_VERTEX,
155         R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN,
156         R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN,
157         R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN,
158         R_SHADOW_RENDERMODE_LIGHT_GLSL,
159         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
160         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
161         R_SHADOW_RENDERMODE_SHADOWMAP2D,
162         R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
163         R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
164 }
165 r_shadow_rendermode_t;
166
167 typedef enum r_shadow_shadowmode_e
168 {
169     R_SHADOW_SHADOWMODE_STENCIL,
170     R_SHADOW_SHADOWMODE_SHADOWMAP2D,
171     R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
172     R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
173 }
174 r_shadow_shadowmode_t;
175
176 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
177 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
178 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
179 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
180 qboolean r_shadow_usingshadowmaprect;
181 qboolean r_shadow_usingshadowmap2d;
182 qboolean r_shadow_usingshadowmapcube;
183 int r_shadow_shadowmapside;
184 float r_shadow_shadowmap_texturescale[2];
185 float r_shadow_shadowmap_parameters[4];
186 #if 0
187 int r_shadow_drawbuffer;
188 int r_shadow_readbuffer;
189 #endif
190 int r_shadow_cullface_front, r_shadow_cullface_back;
191 GLuint r_shadow_fborectangle;
192 GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
193 GLuint r_shadow_fbo2d;
194 r_shadow_shadowmode_t r_shadow_shadowmode;
195 int r_shadow_shadowmapfilterquality;
196 int r_shadow_shadowmaptexturetype;
197 int r_shadow_shadowmapdepthbits;
198 int r_shadow_shadowmapmaxsize;
199 qboolean r_shadow_shadowmapvsdct;
200 qboolean r_shadow_shadowmapsampler;
201 int r_shadow_shadowmappcf;
202 int r_shadow_shadowmapborder;
203 int r_shadow_lightscissor[4];
204 qboolean r_shadow_usingdeferredprepass;
205
206 int maxshadowtriangles;
207 int *shadowelements;
208
209 int maxshadowvertices;
210 float *shadowvertex3f;
211
212 int maxshadowmark;
213 int numshadowmark;
214 int *shadowmark;
215 int *shadowmarklist;
216 int shadowmarkcount;
217
218 int maxshadowsides;
219 int numshadowsides;
220 unsigned char *shadowsides;
221 int *shadowsideslist;
222
223 int maxvertexupdate;
224 int *vertexupdate;
225 int *vertexremap;
226 int vertexupdatenum;
227
228 int r_shadow_buffer_numleafpvsbytes;
229 unsigned char *r_shadow_buffer_visitingleafpvs;
230 unsigned char *r_shadow_buffer_leafpvs;
231 int *r_shadow_buffer_leaflist;
232
233 int r_shadow_buffer_numsurfacepvsbytes;
234 unsigned char *r_shadow_buffer_surfacepvs;
235 int *r_shadow_buffer_surfacelist;
236 unsigned char *r_shadow_buffer_surfacesides;
237
238 int r_shadow_buffer_numshadowtrispvsbytes;
239 unsigned char *r_shadow_buffer_shadowtrispvs;
240 int r_shadow_buffer_numlighttrispvsbytes;
241 unsigned char *r_shadow_buffer_lighttrispvs;
242
243 rtexturepool_t *r_shadow_texturepool;
244 rtexture_t *r_shadow_attenuationgradienttexture;
245 rtexture_t *r_shadow_attenuation2dtexture;
246 rtexture_t *r_shadow_attenuation3dtexture;
247 skinframe_t *r_shadow_lightcorona;
248 rtexture_t *r_shadow_shadowmaprectangletexture;
249 rtexture_t *r_shadow_shadowmap2dtexture;
250 rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
251 rtexture_t *r_shadow_shadowmapvsdcttexture;
252 int r_shadow_shadowmapsize; // changes for each light based on distance
253 int r_shadow_shadowmaplod; // changes for each light based on distance
254
255 GLuint r_shadow_prepassgeometryfbo;
256 GLuint r_shadow_prepasslightingfbo;
257 int r_shadow_prepass_width;
258 int r_shadow_prepass_height;
259 rtexture_t *r_shadow_prepassgeometrydepthtexture;
260 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
261 rtexture_t *r_shadow_prepasslightingdiffusetexture;
262 rtexture_t *r_shadow_prepasslightingspeculartexture;
263
264 // lights are reloaded when this changes
265 char r_shadow_mapname[MAX_QPATH];
266
267 // used only for light filters (cubemaps)
268 rtexturepool_t *r_shadow_filters_texturepool;
269
270 static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
271
272 cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
273 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
274 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
275 cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
276 cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "2", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
277 //cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
278 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
279 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)"};
280 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"};
281 cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
282 cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
283 cvar_t r_shadow_gloss2exponent = {0, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
284 cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
285 cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
286 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
287 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
288 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
289 cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
290 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)"};
291 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
292 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
293 cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
294 cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
295 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)"};
296 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"};
297 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
298 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
299 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"};
300 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)"};
301 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "0", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
302 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)"};
303 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
304 cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
305 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
306 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
307 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
308 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
309 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
310 cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
311 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
312 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
313 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
314 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
315 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
316 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
317 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
318 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
319 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)"};
320 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)"};
321 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
322 cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksm the proportion of hidden pixels controls corona intensity"};
323 cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
324 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
325 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
326 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
327 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
328 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
329 cvar_t r_editlights_cursorpushback = {0, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
330 cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
331 cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
332 cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
333
334 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
335 #define ATTENTABLESIZE 256
336 // 1D gradient, 2D circle and 3D sphere attenuation textures
337 #define ATTEN1DSIZE 32
338 #define ATTEN2DSIZE 64
339 #define ATTEN3DSIZE 32
340
341 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
342 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
343 static float r_shadow_attentable[ATTENTABLESIZE+1];
344
345 rtlight_t *r_shadow_compilingrtlight;
346 static memexpandablearray_t r_shadow_worldlightsarray;
347 dlight_t *r_shadow_selectedlight;
348 dlight_t r_shadow_bufferlight;
349 vec3_t r_editlights_cursorlocation;
350
351 extern int con_vislines;
352
353 typedef struct cubemapinfo_s
354 {
355         char basename[64];
356         rtexture_t *texture;
357 }
358 cubemapinfo_t;
359
360 static int numcubemaps;
361 static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
362
363 void R_Shadow_UncompileWorldLights(void);
364 void R_Shadow_ClearWorldLights(void);
365 void R_Shadow_SaveWorldLights(void);
366 void R_Shadow_LoadWorldLights(void);
367 void R_Shadow_LoadLightsFile(void);
368 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
369 void R_Shadow_EditLights_Reload_f(void);
370 void R_Shadow_ValidateCvars(void);
371 static void R_Shadow_MakeTextures(void);
372
373 #define EDLIGHTSPRSIZE                  8
374 skinframe_t *r_editlights_sprcursor;
375 skinframe_t *r_editlights_sprlight;
376 skinframe_t *r_editlights_sprnoshadowlight;
377 skinframe_t *r_editlights_sprcubemaplight;
378 skinframe_t *r_editlights_sprcubemapnoshadowlight;
379 skinframe_t *r_editlights_sprselection;
380
381 void R_Shadow_SetShadowMode(void)
382 {
383         r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
384         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
385         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
386         r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
387         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
388         r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
389         r_shadow_shadowmaplod = -1;
390         r_shadow_shadowmapsize = 0;
391         r_shadow_shadowmapsampler = false;
392         r_shadow_shadowmappcf = 0;
393         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
394         switch(vid.renderpath)
395         {
396         case RENDERPATH_GL20:
397         case RENDERPATH_CGGL:
398                 if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
399                 {
400                         if(r_shadow_shadowmapfilterquality < 0)
401                         {
402                                 if(strstr(gl_vendor, "NVIDIA")) 
403                                 {
404                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
405                                         r_shadow_shadowmappcf = 1;
406                                 }
407                                 else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) 
408                                         r_shadow_shadowmappcf = 1;
409                                 else if(strstr(gl_vendor, "ATI")) 
410                                         r_shadow_shadowmappcf = 1;
411                                 else 
412                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
413                         }
414                         else 
415                         {
416                                 switch (r_shadow_shadowmapfilterquality)
417                                 {
418                                 case 1:
419                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
420                                         break;
421                                 case 2:
422                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
423                                         r_shadow_shadowmappcf = 1;
424                                         break;
425                                 case 3:
426                                         r_shadow_shadowmappcf = 1;
427                                         break;
428                                 case 4:
429                                         r_shadow_shadowmappcf = 2;
430                                         break;
431                                 }
432                         }
433                         switch (r_shadow_shadowmaptexturetype)
434                         {
435                         case 0:
436                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
437                                 break;
438                         case 1:
439                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
440                                 break;
441                         case 2:
442                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
443                                 break;
444                         default:
445                                 if((vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
446                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
447                                 else if(vid.support.arb_texture_rectangle) 
448                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
449                                 else
450                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
451                                 break;
452                         }
453                 }
454                 break;
455         case RENDERPATH_GL13:
456                 break;
457         case RENDERPATH_GL11:
458                 break;
459         }
460 }
461
462 void R_Shadow_FreeShadowMaps(void)
463 {
464         int i;
465
466         R_Shadow_SetShadowMode();
467
468         if (!vid.support.ext_framebuffer_object || !vid.support.arb_fragment_shader)
469                 return;
470
471         CHECKGLERROR
472
473         if (r_shadow_fborectangle)
474                 qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
475         r_shadow_fborectangle = 0;
476
477         if (r_shadow_fbo2d)
478                 qglDeleteFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
479         r_shadow_fbo2d = 0;
480         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
481                 if (r_shadow_fbocubeside[i])
482                         qglDeleteFramebuffersEXT(1, &r_shadow_fbocubeside[i]);CHECKGLERROR
483         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
484
485         if (r_shadow_shadowmaprectangletexture)
486                 R_FreeTexture(r_shadow_shadowmaprectangletexture);
487         r_shadow_shadowmaprectangletexture = NULL;
488
489         if (r_shadow_shadowmap2dtexture)
490                 R_FreeTexture(r_shadow_shadowmap2dtexture);
491         r_shadow_shadowmap2dtexture = NULL;
492
493         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
494                 if (r_shadow_shadowmapcubetexture[i])
495                         R_FreeTexture(r_shadow_shadowmapcubetexture[i]);
496         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
497
498         if (r_shadow_shadowmapvsdcttexture)
499                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
500         r_shadow_shadowmapvsdcttexture = NULL;
501
502         CHECKGLERROR
503 }
504
505 void r_shadow_start(void)
506 {
507         // allocate vertex processing arrays
508         numcubemaps = 0;
509         r_shadow_attenuationgradienttexture = NULL;
510         r_shadow_attenuation2dtexture = NULL;
511         r_shadow_attenuation3dtexture = NULL;
512         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
513         r_shadow_shadowmaprectangletexture = NULL;
514         r_shadow_shadowmap2dtexture = NULL;
515         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
516         r_shadow_shadowmapvsdcttexture = NULL;
517         r_shadow_shadowmapmaxsize = 0;
518         r_shadow_shadowmapsize = 0;
519         r_shadow_shadowmaplod = 0;
520         r_shadow_shadowmapfilterquality = -1;
521         r_shadow_shadowmaptexturetype = -1;
522         r_shadow_shadowmapdepthbits = 0;
523         r_shadow_shadowmapvsdct = false;
524         r_shadow_shadowmapsampler = false;
525         r_shadow_shadowmappcf = 0;
526         r_shadow_fborectangle = 0;
527         r_shadow_fbo2d = 0;
528         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
529
530         R_Shadow_FreeShadowMaps();
531
532         r_shadow_texturepool = NULL;
533         r_shadow_filters_texturepool = NULL;
534         R_Shadow_ValidateCvars();
535         R_Shadow_MakeTextures();
536         maxshadowtriangles = 0;
537         shadowelements = NULL;
538         maxshadowvertices = 0;
539         shadowvertex3f = NULL;
540         maxvertexupdate = 0;
541         vertexupdate = NULL;
542         vertexremap = NULL;
543         vertexupdatenum = 0;
544         maxshadowmark = 0;
545         numshadowmark = 0;
546         shadowmark = NULL;
547         shadowmarklist = NULL;
548         shadowmarkcount = 0;
549         maxshadowsides = 0;
550         numshadowsides = 0;
551         shadowsides = NULL;
552         shadowsideslist = NULL;
553         r_shadow_buffer_numleafpvsbytes = 0;
554         r_shadow_buffer_visitingleafpvs = NULL;
555         r_shadow_buffer_leafpvs = NULL;
556         r_shadow_buffer_leaflist = NULL;
557         r_shadow_buffer_numsurfacepvsbytes = 0;
558         r_shadow_buffer_surfacepvs = NULL;
559         r_shadow_buffer_surfacelist = NULL;
560         r_shadow_buffer_surfacesides = NULL;
561         r_shadow_buffer_numshadowtrispvsbytes = 0;
562         r_shadow_buffer_shadowtrispvs = NULL;
563         r_shadow_buffer_numlighttrispvsbytes = 0;
564         r_shadow_buffer_lighttrispvs = NULL;
565
566         r_shadow_usingdeferredprepass = false;
567         r_shadow_prepass_width = r_shadow_prepass_height = 0;
568 }
569
570 static void R_Shadow_FreeDeferred(void);
571 void r_shadow_shutdown(void)
572 {
573         CHECKGLERROR
574         R_Shadow_UncompileWorldLights();
575
576         R_Shadow_FreeShadowMaps();
577
578         r_shadow_usingdeferredprepass = false;
579         if (r_shadow_prepass_width)
580                 R_Shadow_FreeDeferred();
581         r_shadow_prepass_width = r_shadow_prepass_height = 0;
582
583         CHECKGLERROR
584         numcubemaps = 0;
585         r_shadow_attenuationgradienttexture = NULL;
586         r_shadow_attenuation2dtexture = NULL;
587         r_shadow_attenuation3dtexture = NULL;
588         R_FreeTexturePool(&r_shadow_texturepool);
589         R_FreeTexturePool(&r_shadow_filters_texturepool);
590         maxshadowtriangles = 0;
591         if (shadowelements)
592                 Mem_Free(shadowelements);
593         shadowelements = NULL;
594         if (shadowvertex3f)
595                 Mem_Free(shadowvertex3f);
596         shadowvertex3f = NULL;
597         maxvertexupdate = 0;
598         if (vertexupdate)
599                 Mem_Free(vertexupdate);
600         vertexupdate = NULL;
601         if (vertexremap)
602                 Mem_Free(vertexremap);
603         vertexremap = NULL;
604         vertexupdatenum = 0;
605         maxshadowmark = 0;
606         numshadowmark = 0;
607         if (shadowmark)
608                 Mem_Free(shadowmark);
609         shadowmark = NULL;
610         if (shadowmarklist)
611                 Mem_Free(shadowmarklist);
612         shadowmarklist = NULL;
613         shadowmarkcount = 0;
614         maxshadowsides = 0;
615         numshadowsides = 0;
616         if (shadowsides)
617                 Mem_Free(shadowsides);
618         shadowsides = NULL;
619         if (shadowsideslist)
620                 Mem_Free(shadowsideslist);
621         shadowsideslist = NULL;
622         r_shadow_buffer_numleafpvsbytes = 0;
623         if (r_shadow_buffer_visitingleafpvs)
624                 Mem_Free(r_shadow_buffer_visitingleafpvs);
625         r_shadow_buffer_visitingleafpvs = NULL;
626         if (r_shadow_buffer_leafpvs)
627                 Mem_Free(r_shadow_buffer_leafpvs);
628         r_shadow_buffer_leafpvs = NULL;
629         if (r_shadow_buffer_leaflist)
630                 Mem_Free(r_shadow_buffer_leaflist);
631         r_shadow_buffer_leaflist = NULL;
632         r_shadow_buffer_numsurfacepvsbytes = 0;
633         if (r_shadow_buffer_surfacepvs)
634                 Mem_Free(r_shadow_buffer_surfacepvs);
635         r_shadow_buffer_surfacepvs = NULL;
636         if (r_shadow_buffer_surfacelist)
637                 Mem_Free(r_shadow_buffer_surfacelist);
638         r_shadow_buffer_surfacelist = NULL;
639         if (r_shadow_buffer_surfacesides)
640                 Mem_Free(r_shadow_buffer_surfacesides);
641         r_shadow_buffer_surfacesides = NULL;
642         r_shadow_buffer_numshadowtrispvsbytes = 0;
643         if (r_shadow_buffer_shadowtrispvs)
644                 Mem_Free(r_shadow_buffer_shadowtrispvs);
645         r_shadow_buffer_numlighttrispvsbytes = 0;
646         if (r_shadow_buffer_lighttrispvs)
647                 Mem_Free(r_shadow_buffer_lighttrispvs);
648 }
649
650 void r_shadow_newmap(void)
651 {
652         if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
653         if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
654         if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
655         if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
656         if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
657         if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
658         if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
659         if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
660                 R_Shadow_EditLights_Reload_f();
661 }
662
663 void R_Shadow_Init(void)
664 {
665         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
666         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
667         Cvar_RegisterVariable(&r_shadow_usenormalmap);
668         Cvar_RegisterVariable(&r_shadow_debuglight);
669         Cvar_RegisterVariable(&r_shadow_deferred);
670         Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
671 //      Cvar_RegisterVariable(&r_shadow_deferred_fp);
672         Cvar_RegisterVariable(&r_shadow_gloss);
673         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
674         Cvar_RegisterVariable(&r_shadow_glossintensity);
675         Cvar_RegisterVariable(&r_shadow_glossexponent);
676         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
677         Cvar_RegisterVariable(&r_shadow_glossexact);
678         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
679         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
680         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
681         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
682         Cvar_RegisterVariable(&r_shadow_projectdistance);
683         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
684         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
685         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
686         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
687         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
688         Cvar_RegisterVariable(&r_shadow_realtime_world);
689         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
690         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
691         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
692         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
693         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
694         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
695         Cvar_RegisterVariable(&r_shadow_scissor);
696         Cvar_RegisterVariable(&r_shadow_shadowmapping);
697         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
698         Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
699         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
700         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
701         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
702         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
703         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
704 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
705 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
706         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
707         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
708         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
709         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
710         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
711         Cvar_RegisterVariable(&r_shadow_polygonfactor);
712         Cvar_RegisterVariable(&r_shadow_polygonoffset);
713         Cvar_RegisterVariable(&r_shadow_texture3d);
714         Cvar_RegisterVariable(&r_coronas);
715         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
716         Cvar_RegisterVariable(&r_coronas_occlusionquery);
717         Cvar_RegisterVariable(&gl_flashblend);
718         Cvar_RegisterVariable(&gl_ext_separatestencil);
719         Cvar_RegisterVariable(&gl_ext_stenciltwoside);
720         if (gamemode == GAME_TENEBRAE)
721         {
722                 Cvar_SetValue("r_shadow_gloss", 2);
723                 Cvar_SetValue("r_shadow_bumpscale_basetexture", 4);
724         }
725         R_Shadow_EditLights_Init();
726         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
727         maxshadowtriangles = 0;
728         shadowelements = NULL;
729         maxshadowvertices = 0;
730         shadowvertex3f = NULL;
731         maxvertexupdate = 0;
732         vertexupdate = NULL;
733         vertexremap = NULL;
734         vertexupdatenum = 0;
735         maxshadowmark = 0;
736         numshadowmark = 0;
737         shadowmark = NULL;
738         shadowmarklist = NULL;
739         shadowmarkcount = 0;
740         maxshadowsides = 0;
741         numshadowsides = 0;
742         shadowsides = NULL;
743         shadowsideslist = NULL;
744         r_shadow_buffer_numleafpvsbytes = 0;
745         r_shadow_buffer_visitingleafpvs = NULL;
746         r_shadow_buffer_leafpvs = NULL;
747         r_shadow_buffer_leaflist = NULL;
748         r_shadow_buffer_numsurfacepvsbytes = 0;
749         r_shadow_buffer_surfacepvs = NULL;
750         r_shadow_buffer_surfacelist = NULL;
751         r_shadow_buffer_surfacesides = NULL;
752         r_shadow_buffer_shadowtrispvs = NULL;
753         r_shadow_buffer_lighttrispvs = NULL;
754         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
755 }
756
757 matrix4x4_t matrix_attenuationxyz =
758 {
759         {
760                 {0.5, 0.0, 0.0, 0.5},
761                 {0.0, 0.5, 0.0, 0.5},
762                 {0.0, 0.0, 0.5, 0.5},
763                 {0.0, 0.0, 0.0, 1.0}
764         }
765 };
766
767 matrix4x4_t matrix_attenuationz =
768 {
769         {
770                 {0.0, 0.0, 0.5, 0.5},
771                 {0.0, 0.0, 0.0, 0.5},
772                 {0.0, 0.0, 0.0, 0.5},
773                 {0.0, 0.0, 0.0, 1.0}
774         }
775 };
776
777 void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
778 {
779         numvertices = ((numvertices + 255) & ~255) * vertscale;
780         numtriangles = ((numtriangles + 255) & ~255) * triscale;
781         // make sure shadowelements is big enough for this volume
782         if (maxshadowtriangles < numtriangles)
783         {
784                 maxshadowtriangles = numtriangles;
785                 if (shadowelements)
786                         Mem_Free(shadowelements);
787                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
788         }
789         // make sure shadowvertex3f is big enough for this volume
790         if (maxshadowvertices < numvertices)
791         {
792                 maxshadowvertices = numvertices;
793                 if (shadowvertex3f)
794                         Mem_Free(shadowvertex3f);
795                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
796         }
797 }
798
799 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
800 {
801         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
802         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
803         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
804         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
805         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
806         {
807                 if (r_shadow_buffer_visitingleafpvs)
808                         Mem_Free(r_shadow_buffer_visitingleafpvs);
809                 if (r_shadow_buffer_leafpvs)
810                         Mem_Free(r_shadow_buffer_leafpvs);
811                 if (r_shadow_buffer_leaflist)
812                         Mem_Free(r_shadow_buffer_leaflist);
813                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
814                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
815                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
816                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
817         }
818         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
819         {
820                 if (r_shadow_buffer_surfacepvs)
821                         Mem_Free(r_shadow_buffer_surfacepvs);
822                 if (r_shadow_buffer_surfacelist)
823                         Mem_Free(r_shadow_buffer_surfacelist);
824                 if (r_shadow_buffer_surfacesides)
825                         Mem_Free(r_shadow_buffer_surfacesides);
826                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
827                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
828                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
829                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
830         }
831         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
832         {
833                 if (r_shadow_buffer_shadowtrispvs)
834                         Mem_Free(r_shadow_buffer_shadowtrispvs);
835                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
836                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
837         }
838         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
839         {
840                 if (r_shadow_buffer_lighttrispvs)
841                         Mem_Free(r_shadow_buffer_lighttrispvs);
842                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
843                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
844         }
845 }
846
847 void R_Shadow_PrepareShadowMark(int numtris)
848 {
849         // make sure shadowmark is big enough for this volume
850         if (maxshadowmark < numtris)
851         {
852                 maxshadowmark = numtris;
853                 if (shadowmark)
854                         Mem_Free(shadowmark);
855                 if (shadowmarklist)
856                         Mem_Free(shadowmarklist);
857                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
858                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
859                 shadowmarkcount = 0;
860         }
861         shadowmarkcount++;
862         // if shadowmarkcount wrapped we clear the array and adjust accordingly
863         if (shadowmarkcount == 0)
864         {
865                 shadowmarkcount = 1;
866                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
867         }
868         numshadowmark = 0;
869 }
870
871 void R_Shadow_PrepareShadowSides(int numtris)
872 {
873     if (maxshadowsides < numtris)
874     {
875         maxshadowsides = numtris;
876         if (shadowsides)
877                         Mem_Free(shadowsides);
878                 if (shadowsideslist)
879                         Mem_Free(shadowsideslist);
880                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
881                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
882         }
883         numshadowsides = 0;
884 }
885
886 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)
887 {
888         int i, j;
889         int outtriangles = 0, outvertices = 0;
890         const int *element;
891         const float *vertex;
892         float ratio, direction[3], projectvector[3];
893
894         if (projectdirection)
895                 VectorScale(projectdirection, projectdistance, projectvector);
896         else
897                 VectorClear(projectvector);
898
899         // create the vertices
900         if (projectdirection)
901         {
902                 for (i = 0;i < numshadowmarktris;i++)
903                 {
904                         element = inelement3i + shadowmarktris[i] * 3;
905                         for (j = 0;j < 3;j++)
906                         {
907                                 if (vertexupdate[element[j]] != vertexupdatenum)
908                                 {
909                                         vertexupdate[element[j]] = vertexupdatenum;
910                                         vertexremap[element[j]] = outvertices;
911                                         vertex = invertex3f + element[j] * 3;
912                                         // project one copy of the vertex according to projectvector
913                                         VectorCopy(vertex, outvertex3f);
914                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
915                                         outvertex3f += 6;
916                                         outvertices += 2;
917                                 }
918                         }
919                 }
920         }
921         else
922         {
923                 for (i = 0;i < numshadowmarktris;i++)
924                 {
925                         element = inelement3i + shadowmarktris[i] * 3;
926                         for (j = 0;j < 3;j++)
927                         {
928                                 if (vertexupdate[element[j]] != vertexupdatenum)
929                                 {
930                                         vertexupdate[element[j]] = vertexupdatenum;
931                                         vertexremap[element[j]] = outvertices;
932                                         vertex = invertex3f + element[j] * 3;
933                                         // project one copy of the vertex to the sphere radius of the light
934                                         // (FIXME: would projecting it to the light box be better?)
935                                         VectorSubtract(vertex, projectorigin, direction);
936                                         ratio = projectdistance / VectorLength(direction);
937                                         VectorCopy(vertex, outvertex3f);
938                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
939                                         outvertex3f += 6;
940                                         outvertices += 2;
941                                 }
942                         }
943                 }
944         }
945
946         if (r_shadow_frontsidecasting.integer)
947         {
948                 for (i = 0;i < numshadowmarktris;i++)
949                 {
950                         int remappedelement[3];
951                         int markindex;
952                         const int *neighbortriangle;
953
954                         markindex = shadowmarktris[i] * 3;
955                         element = inelement3i + markindex;
956                         neighbortriangle = inneighbor3i + markindex;
957                         // output the front and back triangles
958                         outelement3i[0] = vertexremap[element[0]];
959                         outelement3i[1] = vertexremap[element[1]];
960                         outelement3i[2] = vertexremap[element[2]];
961                         outelement3i[3] = vertexremap[element[2]] + 1;
962                         outelement3i[4] = vertexremap[element[1]] + 1;
963                         outelement3i[5] = vertexremap[element[0]] + 1;
964
965                         outelement3i += 6;
966                         outtriangles += 2;
967                         // output the sides (facing outward from this triangle)
968                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
969                         {
970                                 remappedelement[0] = vertexremap[element[0]];
971                                 remappedelement[1] = vertexremap[element[1]];
972                                 outelement3i[0] = remappedelement[1];
973                                 outelement3i[1] = remappedelement[0];
974                                 outelement3i[2] = remappedelement[0] + 1;
975                                 outelement3i[3] = remappedelement[1];
976                                 outelement3i[4] = remappedelement[0] + 1;
977                                 outelement3i[5] = remappedelement[1] + 1;
978
979                                 outelement3i += 6;
980                                 outtriangles += 2;
981                         }
982                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
983                         {
984                                 remappedelement[1] = vertexremap[element[1]];
985                                 remappedelement[2] = vertexremap[element[2]];
986                                 outelement3i[0] = remappedelement[2];
987                                 outelement3i[1] = remappedelement[1];
988                                 outelement3i[2] = remappedelement[1] + 1;
989                                 outelement3i[3] = remappedelement[2];
990                                 outelement3i[4] = remappedelement[1] + 1;
991                                 outelement3i[5] = remappedelement[2] + 1;
992
993                                 outelement3i += 6;
994                                 outtriangles += 2;
995                         }
996                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
997                         {
998                                 remappedelement[0] = vertexremap[element[0]];
999                                 remappedelement[2] = vertexremap[element[2]];
1000                                 outelement3i[0] = remappedelement[0];
1001                                 outelement3i[1] = remappedelement[2];
1002                                 outelement3i[2] = remappedelement[2] + 1;
1003                                 outelement3i[3] = remappedelement[0];
1004                                 outelement3i[4] = remappedelement[2] + 1;
1005                                 outelement3i[5] = remappedelement[0] + 1;
1006
1007                                 outelement3i += 6;
1008                                 outtriangles += 2;
1009                         }
1010                 }
1011         }
1012         else
1013         {
1014                 for (i = 0;i < numshadowmarktris;i++)
1015                 {
1016                         int remappedelement[3];
1017                         int markindex;
1018                         const int *neighbortriangle;
1019
1020                         markindex = shadowmarktris[i] * 3;
1021                         element = inelement3i + markindex;
1022                         neighbortriangle = inneighbor3i + markindex;
1023                         // output the front and back triangles
1024                         outelement3i[0] = vertexremap[element[2]];
1025                         outelement3i[1] = vertexremap[element[1]];
1026                         outelement3i[2] = vertexremap[element[0]];
1027                         outelement3i[3] = vertexremap[element[0]] + 1;
1028                         outelement3i[4] = vertexremap[element[1]] + 1;
1029                         outelement3i[5] = vertexremap[element[2]] + 1;
1030
1031                         outelement3i += 6;
1032                         outtriangles += 2;
1033                         // output the sides (facing outward from this triangle)
1034                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1035                         {
1036                                 remappedelement[0] = vertexremap[element[0]];
1037                                 remappedelement[1] = vertexremap[element[1]];
1038                                 outelement3i[0] = remappedelement[0];
1039                                 outelement3i[1] = remappedelement[1];
1040                                 outelement3i[2] = remappedelement[1] + 1;
1041                                 outelement3i[3] = remappedelement[0];
1042                                 outelement3i[4] = remappedelement[1] + 1;
1043                                 outelement3i[5] = remappedelement[0] + 1;
1044
1045                                 outelement3i += 6;
1046                                 outtriangles += 2;
1047                         }
1048                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1049                         {
1050                                 remappedelement[1] = vertexremap[element[1]];
1051                                 remappedelement[2] = vertexremap[element[2]];
1052                                 outelement3i[0] = remappedelement[1];
1053                                 outelement3i[1] = remappedelement[2];
1054                                 outelement3i[2] = remappedelement[2] + 1;
1055                                 outelement3i[3] = remappedelement[1];
1056                                 outelement3i[4] = remappedelement[2] + 1;
1057                                 outelement3i[5] = remappedelement[1] + 1;
1058
1059                                 outelement3i += 6;
1060                                 outtriangles += 2;
1061                         }
1062                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1063                         {
1064                                 remappedelement[0] = vertexremap[element[0]];
1065                                 remappedelement[2] = vertexremap[element[2]];
1066                                 outelement3i[0] = remappedelement[2];
1067                                 outelement3i[1] = remappedelement[0];
1068                                 outelement3i[2] = remappedelement[0] + 1;
1069                                 outelement3i[3] = remappedelement[2];
1070                                 outelement3i[4] = remappedelement[0] + 1;
1071                                 outelement3i[5] = remappedelement[2] + 1;
1072
1073                                 outelement3i += 6;
1074                                 outtriangles += 2;
1075                         }
1076                 }
1077         }
1078         if (outnumvertices)
1079                 *outnumvertices = outvertices;
1080         return outtriangles;
1081 }
1082
1083 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)
1084 {
1085         int i, j, k;
1086         int outtriangles = 0, outvertices = 0;
1087         const int *element;
1088         const float *vertex;
1089         float ratio, direction[3], projectvector[3];
1090         qboolean side[4];
1091
1092         if (projectdirection)
1093                 VectorScale(projectdirection, projectdistance, projectvector);
1094         else
1095                 VectorClear(projectvector);
1096
1097         for (i = 0;i < numshadowmarktris;i++)
1098         {
1099                 int remappedelement[3];
1100                 int markindex;
1101                 const int *neighbortriangle;
1102
1103                 markindex = shadowmarktris[i] * 3;
1104                 neighbortriangle = inneighbor3i + markindex;
1105                 side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
1106                 side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
1107                 side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
1108                 if (side[0] + side[1] + side[2] == 0)
1109                         continue;
1110
1111                 side[3] = side[0];
1112                 element = inelement3i + markindex;
1113
1114                 // create the vertices
1115                 for (j = 0;j < 3;j++)
1116                 {
1117                         if (side[j] + side[j+1] == 0)
1118                                 continue;
1119                         k = element[j];
1120                         if (vertexupdate[k] != vertexupdatenum)
1121                         {
1122                                 vertexupdate[k] = vertexupdatenum;
1123                                 vertexremap[k] = outvertices;
1124                                 vertex = invertex3f + k * 3;
1125                                 VectorCopy(vertex, outvertex3f);
1126                                 if (projectdirection)
1127                                 {
1128                                         // project one copy of the vertex according to projectvector
1129                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1130                                 }
1131                                 else
1132                                 {
1133                                         // project one copy of the vertex to the sphere radius of the light
1134                                         // (FIXME: would projecting it to the light box be better?)
1135                                         VectorSubtract(vertex, projectorigin, direction);
1136                                         ratio = projectdistance / VectorLength(direction);
1137                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1138                                 }
1139                                 outvertex3f += 6;
1140                                 outvertices += 2;
1141                         }
1142                 }
1143
1144                 // output the sides (facing outward from this triangle)
1145                 if (!side[0])
1146                 {
1147                         remappedelement[0] = vertexremap[element[0]];
1148                         remappedelement[1] = vertexremap[element[1]];
1149                         outelement3i[0] = remappedelement[1];
1150                         outelement3i[1] = remappedelement[0];
1151                         outelement3i[2] = remappedelement[0] + 1;
1152                         outelement3i[3] = remappedelement[1];
1153                         outelement3i[4] = remappedelement[0] + 1;
1154                         outelement3i[5] = remappedelement[1] + 1;
1155
1156                         outelement3i += 6;
1157                         outtriangles += 2;
1158                 }
1159                 if (!side[1])
1160                 {
1161                         remappedelement[1] = vertexremap[element[1]];
1162                         remappedelement[2] = vertexremap[element[2]];
1163                         outelement3i[0] = remappedelement[2];
1164                         outelement3i[1] = remappedelement[1];
1165                         outelement3i[2] = remappedelement[1] + 1;
1166                         outelement3i[3] = remappedelement[2];
1167                         outelement3i[4] = remappedelement[1] + 1;
1168                         outelement3i[5] = remappedelement[2] + 1;
1169
1170                         outelement3i += 6;
1171                         outtriangles += 2;
1172                 }
1173                 if (!side[2])
1174                 {
1175                         remappedelement[0] = vertexremap[element[0]];
1176                         remappedelement[2] = vertexremap[element[2]];
1177                         outelement3i[0] = remappedelement[0];
1178                         outelement3i[1] = remappedelement[2];
1179                         outelement3i[2] = remappedelement[2] + 1;
1180                         outelement3i[3] = remappedelement[0];
1181                         outelement3i[4] = remappedelement[2] + 1;
1182                         outelement3i[5] = remappedelement[0] + 1;
1183
1184                         outelement3i += 6;
1185                         outtriangles += 2;
1186                 }
1187         }
1188         if (outnumvertices)
1189                 *outnumvertices = outvertices;
1190         return outtriangles;
1191 }
1192
1193 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)
1194 {
1195         int t, tend;
1196         const int *e;
1197         const float *v[3];
1198         float normal[3];
1199         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1200                 return;
1201         tend = firsttriangle + numtris;
1202         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1203         {
1204                 // surface box entirely inside light box, no box cull
1205                 if (projectdirection)
1206                 {
1207                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1208                         {
1209                                 TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
1210                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1211                                         shadowmarklist[numshadowmark++] = t;
1212                         }
1213                 }
1214                 else
1215                 {
1216                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1217                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
1218                                         shadowmarklist[numshadowmark++] = t;
1219                 }
1220         }
1221         else
1222         {
1223                 // surface box not entirely inside light box, cull each triangle
1224                 if (projectdirection)
1225                 {
1226                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1227                         {
1228                                 v[0] = invertex3f + e[0] * 3;
1229                                 v[1] = invertex3f + e[1] * 3;
1230                                 v[2] = invertex3f + e[2] * 3;
1231                                 TriangleNormal(v[0], v[1], v[2], normal);
1232                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1233                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1234                                         shadowmarklist[numshadowmark++] = t;
1235                         }
1236                 }
1237                 else
1238                 {
1239                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1240                         {
1241                                 v[0] = invertex3f + e[0] * 3;
1242                                 v[1] = invertex3f + e[1] * 3;
1243                                 v[2] = invertex3f + e[2] * 3;
1244                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1245                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1246                                         shadowmarklist[numshadowmark++] = t;
1247                         }
1248                 }
1249         }
1250 }
1251
1252 qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
1253 {
1254 #if 1
1255         return false;
1256 #else
1257         if (r_shadow_compilingrtlight || !r_shadow_frontsidecasting.integer || !r_shadow_usezpassifpossible.integer)
1258                 return false;
1259         // check if the shadow volume intersects the near plane
1260         //
1261         // a ray between the eye and light origin may intersect the caster,
1262         // indicating that the shadow may touch the eye location, however we must
1263         // test the near plane (a polygon), not merely the eye location, so it is
1264         // easiest to enlarge the caster bounding shape slightly for this.
1265         // TODO
1266         return true;
1267 #endif
1268 }
1269
1270 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)
1271 {
1272         int i, tris, outverts;
1273         if (projectdistance < 0.1)
1274         {
1275                 Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
1276                 return;
1277         }
1278         if (!numverts || !nummarktris)
1279                 return;
1280         // make sure shadowelements is big enough for this volume
1281         if (maxshadowtriangles < nummarktris*8 || maxshadowvertices < numverts*2)
1282                 R_Shadow_ResizeShadowArrays(numverts, nummarktris, 2, 8);
1283
1284         if (maxvertexupdate < numverts)
1285         {
1286                 maxvertexupdate = numverts;
1287                 if (vertexupdate)
1288                         Mem_Free(vertexupdate);
1289                 if (vertexremap)
1290                         Mem_Free(vertexremap);
1291                 vertexupdate = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1292                 vertexremap = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1293                 vertexupdatenum = 0;
1294         }
1295         vertexupdatenum++;
1296         if (vertexupdatenum == 0)
1297         {
1298                 vertexupdatenum = 1;
1299                 memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
1300                 memset(vertexremap, 0, maxvertexupdate * sizeof(int));
1301         }
1302
1303         for (i = 0;i < nummarktris;i++)
1304                 shadowmark[marktris[i]] = shadowmarkcount;
1305
1306         if (r_shadow_compilingrtlight)
1307         {
1308                 // if we're compiling an rtlight, capture the mesh
1309                 //tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1310                 //Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zpass, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1311                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1312                 Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zfail, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1313         }
1314         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1315         {
1316                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1317                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1318                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1319         }
1320         else
1321         {
1322                 // decide which type of shadow to generate and set stencil mode
1323                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1324                 // generate the sides or a solid volume, depending on type
1325                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1326                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1327                 else
1328                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1329                 r_refdef.stats.lights_dynamicshadowtriangles += tris;
1330                 r_refdef.stats.lights_shadowtriangles += tris;
1331                 CHECKGLERROR
1332                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1333                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1334                 {
1335                         // increment stencil if frontface is infront of depthbuffer
1336                         GL_CullFace(r_refdef.view.cullface_front);
1337                         qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
1338                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1339                         // decrement stencil if backface is infront of depthbuffer
1340                         GL_CullFace(r_refdef.view.cullface_back);
1341                         qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
1342                 }
1343                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1344                 {
1345                         // decrement stencil if backface is behind depthbuffer
1346                         GL_CullFace(r_refdef.view.cullface_front);
1347                         qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
1348                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1349                         // increment stencil if frontface is behind depthbuffer
1350                         GL_CullFace(r_refdef.view.cullface_back);
1351                         qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
1352                 }
1353                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1354                 CHECKGLERROR
1355         }
1356 }
1357
1358 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1359 {
1360     // p1, p2, p3 are in the cubemap's local coordinate system
1361     // bias = border/(size - border)
1362         int mask = 0x3F;
1363
1364     float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1365           dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1366           dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1367         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1368         mask &= (3<<4)
1369                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1370                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1371                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1372     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1373         mask &= (3<<4)
1374             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1375             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))            
1376             | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1377
1378     dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1379     dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1380     dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1381     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1382         mask &= (3<<0)
1383             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1384             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))            
1385             | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1386     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1387         mask &= (3<<0)
1388             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1389             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1390             | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1391
1392     dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1393     dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1394     dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1395     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1396         mask &= (3<<2)
1397             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1398             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1399             | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1400     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1401         mask &= (3<<2)
1402             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1403             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1404             | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1405
1406         return mask;
1407 }
1408
1409 int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1410 {
1411         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1412         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1413         int mask = 0x3F;
1414
1415         VectorSubtract(maxs, mins, radius);
1416     VectorScale(radius, 0.5f, radius);
1417     VectorAdd(mins, radius, center);
1418     Matrix4x4_Transform(worldtolight, center, lightcenter);
1419         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1420         VectorSubtract(lightcenter, lightradius, pmin);
1421         VectorAdd(lightcenter, lightradius, pmax);
1422
1423     dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1424     dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1425     if(ap1 > bias*an1 && ap2 > bias*an2)
1426         mask &= (3<<4)
1427             | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1428             | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1429     if(an1 > bias*ap1 && an2 > bias*ap2)
1430         mask &= (3<<4)
1431             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1432             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1433
1434     dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1435     dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1436     if(ap1 > bias*an1 && ap2 > bias*an2)
1437         mask &= (3<<0)
1438             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1439             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1440     if(an1 > bias*ap1 && an2 > bias*ap2)
1441         mask &= (3<<0)
1442             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1443             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1444
1445     dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1446     dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1447     if(ap1 > bias*an1 && ap2 > bias*an2)
1448         mask &= (3<<2)
1449             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1450             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1451     if(an1 > bias*ap1 && an2 > bias*ap2)
1452         mask &= (3<<2)
1453             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1454             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1455
1456     return mask;
1457 }
1458
1459 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1460
1461 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1462 {
1463     // p is in the cubemap's local coordinate system
1464     // bias = border/(size - border)
1465     float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1466     float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1467     float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1468     int mask = 0x3F;
1469     if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1470     if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1471     if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1472     if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1473     if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1474     if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1475     return mask;
1476 }
1477
1478 int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1479 {
1480         int i;
1481         vec3_t p, n;
1482         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1483         float scale = (size - 2*border)/size, len;
1484         float bias = border / (float)(size - border), dp, dn, ap, an;
1485         // check if cone enclosing side would cross frustum plane 
1486         scale = 2 / (scale*scale + 2);
1487         for (i = 0;i < 5;i++)
1488         {
1489                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
1490                         continue;
1491                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1492                 len = scale*VectorLength2(n);
1493                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1494                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1495                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1496         }
1497         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1498         {
1499         Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1500         len = scale*VectorLength(n);
1501                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1502                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1503                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1504         }
1505         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1506         // check if frustum corners/origin cross plane sides
1507         for (i = 0;i < 5;i++)
1508         {
1509                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1510                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
1511                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1512                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1513                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
1514                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1515                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1516                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
1517                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1518                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1519         }
1520         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1521 }
1522
1523 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)
1524 {
1525         int t, tend;
1526         const int *e;
1527         const float *v[3];
1528         float normal[3];
1529         vec3_t p[3];
1530         float bias;
1531         int mask, surfacemask = 0;
1532         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1533                 return 0;
1534         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1535         tend = firsttriangle + numtris;
1536         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1537         {
1538                 // surface box entirely inside light box, no box cull
1539                 if (projectdirection)
1540                 {
1541                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1542                         {
1543                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1544                                 TriangleNormal(v[0], v[1], v[2], normal);
1545                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1546                                 {
1547                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1548                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1549                                         surfacemask |= mask;
1550                                         if(totals)
1551                                         {
1552                                                 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;
1553                                                 shadowsides[numshadowsides] = mask;
1554                                                 shadowsideslist[numshadowsides++] = t;
1555                                         }
1556                                 }
1557                         }
1558                 }
1559                 else
1560                 {
1561                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1562                         {
1563                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1564                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1565                                 {
1566                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1567                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1568                                         surfacemask |= mask;
1569                                         if(totals)
1570                                         {
1571                                                 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;
1572                                                 shadowsides[numshadowsides] = mask;
1573                                                 shadowsideslist[numshadowsides++] = t;
1574                                         }
1575                                 }
1576                         }
1577                 }
1578         }
1579         else
1580         {
1581                 // surface box not entirely inside light box, cull each triangle
1582                 if (projectdirection)
1583                 {
1584                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1585                         {
1586                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1587                                 TriangleNormal(v[0], v[1], v[2], normal);
1588                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1589                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1590                                 {
1591                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1592                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1593                                         surfacemask |= mask;
1594                                         if(totals)
1595                                         {
1596                                                 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;
1597                                                 shadowsides[numshadowsides] = mask;
1598                                                 shadowsideslist[numshadowsides++] = t;
1599                                         }
1600                                 }
1601                         }
1602                 }
1603                 else
1604                 {
1605                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1606                         {
1607                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1608                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1609                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1610                                 {
1611                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1612                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1613                                         surfacemask |= mask;
1614                                         if(totals)
1615                                         {
1616                                                 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;
1617                                                 shadowsides[numshadowsides] = mask;
1618                                                 shadowsideslist[numshadowsides++] = t;
1619                                         }
1620                                 }
1621                         }
1622                 }
1623         }
1624         return surfacemask;
1625 }
1626
1627 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)
1628 {
1629         int i, j, outtriangles = 0;
1630         int *outelement3i[6];
1631         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1632                 return;
1633         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1634         // make sure shadowelements is big enough for this mesh
1635         if (maxshadowtriangles < outtriangles)
1636                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1637
1638         // compute the offset and size of the separate index lists for each cubemap side
1639         outtriangles = 0;
1640         for (i = 0;i < 6;i++)
1641         {
1642                 outelement3i[i] = shadowelements + outtriangles * 3;
1643                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1644                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1645                 outtriangles += sidetotals[i];
1646         }
1647
1648         // gather up the (sparse) triangles into separate index lists for each cubemap side
1649         for (i = 0;i < numsidetris;i++)
1650         {
1651                 const int *element = elements + sidetris[i] * 3;
1652                 for (j = 0;j < 6;j++)
1653                 {
1654                         if (sides[i] & (1 << j))
1655                         {
1656                                 outelement3i[j][0] = element[0];
1657                                 outelement3i[j][1] = element[1];
1658                                 outelement3i[j][2] = element[2];
1659                                 outelement3i[j] += 3;
1660                         }
1661                 }
1662         }
1663                         
1664         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1665 }
1666
1667 static void R_Shadow_MakeTextures_MakeCorona(void)
1668 {
1669         float dx, dy;
1670         int x, y, a;
1671         unsigned char pixels[32][32][4];
1672         for (y = 0;y < 32;y++)
1673         {
1674                 dy = (y - 15.5f) * (1.0f / 16.0f);
1675                 for (x = 0;x < 32;x++)
1676                 {
1677                         dx = (x - 15.5f) * (1.0f / 16.0f);
1678                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1679                         a = bound(0, a, 255);
1680                         pixels[y][x][0] = a;
1681                         pixels[y][x][1] = a;
1682                         pixels[y][x][2] = a;
1683                         pixels[y][x][3] = 255;
1684                 }
1685         }
1686         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
1687 }
1688
1689 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1690 {
1691         float dist = sqrt(x*x+y*y+z*z);
1692         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1693         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1694         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1695 }
1696
1697 static void R_Shadow_MakeTextures(void)
1698 {
1699         int x, y, z;
1700         float intensity, dist;
1701         unsigned int *data;
1702         R_Shadow_FreeShadowMaps();
1703         R_FreeTexturePool(&r_shadow_texturepool);
1704         r_shadow_texturepool = R_AllocTexturePool();
1705         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1706         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1707         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1708         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1709         for (x = 0;x <= ATTENTABLESIZE;x++)
1710         {
1711                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1712                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1713                 r_shadow_attentable[x] = bound(0, intensity, 1);
1714         }
1715         // 1D gradient texture
1716         for (x = 0;x < ATTEN1DSIZE;x++)
1717                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1718         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1719         // 2D circle texture
1720         for (y = 0;y < ATTEN2DSIZE;y++)
1721                 for (x = 0;x < ATTEN2DSIZE;x++)
1722                         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);
1723         r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1724         // 3D sphere texture
1725         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1726         {
1727                 for (z = 0;z < ATTEN3DSIZE;z++)
1728                         for (y = 0;y < ATTEN3DSIZE;y++)
1729                                 for (x = 0;x < ATTEN3DSIZE;x++)
1730                                         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));
1731                 r_shadow_attenuation3dtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation3d", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1732         }
1733         else
1734                 r_shadow_attenuation3dtexture = NULL;
1735         Mem_Free(data);
1736
1737         R_Shadow_MakeTextures_MakeCorona();
1738
1739         // Editor light sprites
1740         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1741         "................"
1742         ".3............3."
1743         "..5...2332...5.."
1744         "...7.3....3.7..."
1745         "....7......7...."
1746         "...3.7....7.3..."
1747         "..2...7..7...2.."
1748         "..3..........3.."
1749         "..3..........3.."
1750         "..2...7..7...2.."
1751         "...3.7....7.3..."
1752         "....7......7...."
1753         "...7.3....3.7..."
1754         "..5...2332...5.."
1755         ".3............3."
1756         "................"
1757         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1758         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1759         "................"
1760         "................"
1761         "......1111......"
1762         "....11233211...."
1763         "...1234554321..."
1764         "...1356776531..."
1765         "..124677776421.."
1766         "..135777777531.."
1767         "..135777777531.."
1768         "..124677776421.."
1769         "...1356776531..."
1770         "...1234554321..."
1771         "....11233211...."
1772         "......1111......"
1773         "................"
1774         "................"
1775         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1776         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1777         "................"
1778         "................"
1779         "......1111......"
1780         "....11233211...."
1781         "...1234554321..."
1782         "...1356226531..."
1783         "..12462..26421.."
1784         "..1352....2531.."
1785         "..1352....2531.."
1786         "..12462..26421.."
1787         "...1356226531..."
1788         "...1234554321..."
1789         "....11233211...."
1790         "......1111......"
1791         "................"
1792         "................"
1793         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1794         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1795         "................"
1796         "................"
1797         "......2772......"
1798         "....27755772...."
1799         "..277533335772.."
1800         "..753333333357.."
1801         "..777533335777.."
1802         "..735775577537.."
1803         "..733357753337.."
1804         "..733337733337.."
1805         "..753337733357.."
1806         "..277537735772.."
1807         "....27777772...."
1808         "......2772......"
1809         "................"
1810         "................"
1811         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1812         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1813         "................"
1814         "................"
1815         "......2772......"
1816         "....27722772...."
1817         "..2772....2772.."
1818         "..72........27.."
1819         "..7772....2777.."
1820         "..7.27722772.7.."
1821         "..7...2772...7.."
1822         "..7....77....7.."
1823         "..72...77...27.."
1824         "..2772.77.2772.."
1825         "....27777772...."
1826         "......2772......"
1827         "................"
1828         "................"
1829         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1830         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1831         "................"
1832         ".777752..257777."
1833         ".742........247."
1834         ".72..........27."
1835         ".7............7."
1836         ".5............5."
1837         ".2............2."
1838         "................"
1839         "................"
1840         ".2............2."
1841         ".5............5."
1842         ".7............7."
1843         ".72..........27."
1844         ".742........247."
1845         ".777752..257777."
1846         "................"
1847         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1848 }
1849
1850 void R_Shadow_ValidateCvars(void)
1851 {
1852         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
1853                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
1854         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
1855                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
1856         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
1857                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
1858 }
1859
1860 void R_Shadow_RenderMode_Begin(void)
1861 {
1862 #if 0
1863         GLint drawbuffer;
1864         GLint readbuffer;
1865 #endif
1866         R_Shadow_ValidateCvars();
1867
1868         if (!r_shadow_attenuation2dtexture
1869          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
1870          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1871          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1872                 R_Shadow_MakeTextures();
1873
1874         CHECKGLERROR
1875         R_Mesh_ColorPointer(NULL, 0, 0);
1876         R_Mesh_ResetTextureState();
1877         GL_BlendFunc(GL_ONE, GL_ZERO);
1878         GL_DepthRange(0, 1);
1879         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1880         GL_DepthTest(true);
1881         GL_DepthMask(false);
1882         GL_Color(0, 0, 0, 1);
1883         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1884
1885         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1886
1887         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
1888         {
1889                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
1890                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
1891         }
1892         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
1893         {
1894                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
1895                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
1896         }
1897         else
1898         {
1899                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
1900                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
1901         }
1902
1903         switch(vid.renderpath)
1904         {
1905         case RENDERPATH_GL20:
1906         case RENDERPATH_CGGL:
1907                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1908                 break;
1909         case RENDERPATH_GL13:
1910         case RENDERPATH_GL11:
1911                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
1912                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
1913                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
1914                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
1915                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
1916                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
1917                 else
1918                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
1919                 break;
1920         }
1921
1922         CHECKGLERROR
1923 #if 0
1924         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1925         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1926         r_shadow_drawbuffer = drawbuffer;
1927         r_shadow_readbuffer = readbuffer;
1928 #endif
1929         r_shadow_cullface_front = r_refdef.view.cullface_front;
1930         r_shadow_cullface_back = r_refdef.view.cullface_back;
1931 }
1932
1933 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
1934 {
1935         rsurface.rtlight = rtlight;
1936 }
1937
1938 void R_Shadow_RenderMode_Reset(void)
1939 {
1940         CHECKGLERROR
1941         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE)
1942         {
1943                 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1944         }
1945         if (vid.support.ext_framebuffer_object)
1946         {
1947                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
1948         }
1949 #if 0
1950         qglDrawBuffer(r_shadow_drawbuffer);CHECKGLERROR
1951         qglReadBuffer(r_shadow_readbuffer);CHECKGLERROR
1952 #endif
1953         R_SetViewport(&r_refdef.view.viewport);
1954         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
1955         R_Mesh_ColorPointer(NULL, 0, 0);
1956         R_Mesh_ResetTextureState();
1957         GL_DepthRange(0, 1);
1958         GL_DepthTest(true);
1959         GL_DepthMask(false);
1960         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1961         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1962         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1963         qglStencilMask(~0);CHECKGLERROR
1964         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1965         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1966         r_refdef.view.cullface_front = r_shadow_cullface_front;
1967         r_refdef.view.cullface_back = r_shadow_cullface_back;
1968         GL_CullFace(r_refdef.view.cullface_back);
1969         GL_Color(1, 1, 1, 1);
1970         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
1971         GL_BlendFunc(GL_ONE, GL_ZERO);
1972         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
1973         r_shadow_usingshadowmaprect = false;
1974         r_shadow_usingshadowmapcube = false;
1975         r_shadow_usingshadowmap2d = false;
1976         CHECKGLERROR
1977 }
1978
1979 void R_Shadow_ClearStencil(void)
1980 {
1981         CHECKGLERROR
1982         GL_Clear(GL_STENCIL_BUFFER_BIT);
1983         r_refdef.stats.lights_clears++;
1984 }
1985
1986 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
1987 {
1988         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
1989         if (r_shadow_rendermode == mode)
1990                 return;
1991         CHECKGLERROR
1992         R_Shadow_RenderMode_Reset();
1993         GL_ColorMask(0, 0, 0, 0);
1994         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
1995         R_SetupShader_DepthOrShadow();
1996         qglDepthFunc(GL_LESS);CHECKGLERROR
1997         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1998         r_shadow_rendermode = mode;
1999         switch(mode)
2000         {
2001         default:
2002                 break;
2003         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
2004                 GL_CullFace(GL_NONE);
2005                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
2006                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
2007                 break;
2008         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
2009                 GL_CullFace(GL_NONE);
2010                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
2011                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
2012                 break;
2013         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
2014                 GL_CullFace(GL_NONE);
2015                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2016                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
2017                 qglStencilMask(~0);CHECKGLERROR
2018                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
2019                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
2020                 qglStencilMask(~0);CHECKGLERROR
2021                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
2022                 break;
2023         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2024                 GL_CullFace(GL_NONE);
2025                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2026                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
2027                 qglStencilMask(~0);CHECKGLERROR
2028                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
2029                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
2030                 qglStencilMask(~0);CHECKGLERROR
2031                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
2032                 break;
2033         }
2034 }
2035
2036 static void R_Shadow_MakeVSDCT(void)
2037 {
2038         // maps to a 2x3 texture rectangle with normalized coordinates
2039         // +-
2040         // XX
2041         // YY
2042         // ZZ
2043         // stores abs(dir.xy), offset.xy/2.5
2044         unsigned char data[4*6] =
2045         {
2046                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2047                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2048                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2049                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2050                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2051                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2052         };
2053         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, NULL);
2054 }
2055
2056 void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
2057 {
2058         int status;
2059         int maxsize;
2060         float nearclip, farclip, bias;
2061         r_viewport_t viewport;
2062         GLuint fbo = 0;
2063         CHECKGLERROR
2064         maxsize = r_shadow_shadowmapmaxsize;
2065         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2066         farclip = 1.0f;
2067         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2068         r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2069         r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2070         r_shadow_shadowmapside = side;
2071         r_shadow_shadowmapsize = size;
2072         if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2073         {
2074                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2075                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2076                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2077                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
2078
2079                 // complex unrolled cube approach (more flexible)
2080                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2081                         R_Shadow_MakeVSDCT();
2082                 if (!r_shadow_shadowmap2dtexture)
2083                 {
2084 #if 1
2085                         int w = maxsize*2, h = vid.support.arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
2086                         r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2087                         qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
2088                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
2089                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
2090             // render depth into the fbo, do not render color at all
2091                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2092                         qglReadBuffer(GL_NONE);CHECKGLERROR
2093                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2094                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2095                         {
2096                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2097                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2098                                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
2099                         }
2100 #endif
2101                 }
2102                 CHECKGLERROR
2103                 if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
2104                 r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
2105                 r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
2106                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2107         }
2108         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2109         {
2110                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2111                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2112                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2113                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
2114
2115                 // complex unrolled cube approach (more flexible)
2116                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2117                         R_Shadow_MakeVSDCT();
2118                 if (!r_shadow_shadowmaprectangletexture)
2119                 {
2120 #if 1
2121                         r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2122                         qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
2123                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
2124                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
2125                         // render depth into the fbo, do not render color at all
2126                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2127                         qglReadBuffer(GL_NONE);CHECKGLERROR
2128                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2129                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2130                         {
2131                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2132                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2133                                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
2134                         }
2135 #endif
2136                 }
2137                 CHECKGLERROR
2138                 if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
2139                 r_shadow_shadowmap_texturescale[0] = 1.0f;
2140                 r_shadow_shadowmap_texturescale[1] = 1.0f;
2141                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
2142         }
2143         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2144         {
2145                 r_shadow_shadowmap_parameters[0] = 1.0f;
2146                 r_shadow_shadowmap_parameters[1] = 1.0f;
2147                 R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
2148                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
2149
2150                 // simple cube approach
2151                 if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
2152                 {
2153  #if 1
2154                         r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2155                         qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2156                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2157                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2158                         // render depth into the fbo, do not render color at all
2159                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2160                         qglReadBuffer(GL_NONE);CHECKGLERROR
2161                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2162                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2163                         {
2164                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2165                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2166                                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
2167                         }
2168  #endif
2169                 }
2170                 CHECKGLERROR
2171                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
2172                 r_shadow_shadowmap_texturescale[0] = 0.0f;
2173                 r_shadow_shadowmap_texturescale[1] = 0.0f;
2174                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
2175         }
2176
2177         R_Shadow_RenderMode_Reset();
2178         if (fbo)
2179         {
2180                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
2181                 R_SetupShader_DepthOrShadow();
2182         }
2183         else
2184         {
2185                 R_SetupShader_ShowDepth();
2186                 qglClearColor(1,1,1,1);CHECKGLERROR
2187         }
2188         CHECKGLERROR
2189         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2190         GL_DepthMask(true);
2191         GL_DepthTest(true);
2192         qglClearDepth(1);
2193         CHECKGLERROR
2194
2195 init_done:
2196         R_SetViewport(&viewport);
2197         if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE)
2198         {
2199                 int flipped = (side & 1) ^ (side >> 2);
2200                 r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2201                 r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2202                 GL_CullFace(r_refdef.view.cullface_back);
2203                 if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
2204                 {
2205                         // get tightest scissor rectangle that encloses all viewports in the clear mask
2206                         int x1 = clear & 0x15 ? 0 : size;
2207                         int x2 = clear & 0x2A ? 2 * size : size;
2208                         int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
2209                         int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
2210                         GL_Scissor(x1, y1, x2 - x1, y2 - y1);
2211                         GL_Clear(GL_DEPTH_BUFFER_BIT);
2212                 }
2213                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2214         }
2215         else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE)
2216         {
2217                 qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2218                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2219                 if (clear)
2220                         GL_Clear(GL_DEPTH_BUFFER_BIT);
2221         }
2222         CHECKGLERROR
2223 }
2224
2225 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
2226 {
2227         if (transparent)
2228         {
2229                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2230                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2231                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2232                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2233         }
2234         CHECKGLERROR
2235         R_Shadow_RenderMode_Reset();
2236         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2237         if (!transparent)
2238         {
2239                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2240         }
2241         if (stenciltest)
2242         {
2243                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2244                 // only draw light where this geometry was already rendered AND the
2245                 // stencil is 128 (values other than this mean shadow)
2246                 qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
2247         }
2248         r_shadow_rendermode = r_shadow_lightingrendermode;
2249         // do global setup needed for the chosen lighting mode
2250         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2251         {
2252                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2253                 CHECKGLERROR
2254         }
2255         if (shadowmapping)
2256         {
2257                 if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2258                         r_shadow_usingshadowmap2d = true;
2259                 else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2260                         r_shadow_usingshadowmaprect = true;
2261                 else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2262                         r_shadow_usingshadowmapcube = true;
2263         }
2264         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
2265         CHECKGLERROR
2266 }
2267
2268 static const unsigned short bboxelements[36] =
2269 {
2270         5, 1, 3, 5, 3, 7,
2271         6, 2, 0, 6, 0, 4,
2272         7, 3, 2, 7, 2, 6,
2273         4, 0, 1, 4, 1, 5,
2274         4, 5, 7, 4, 7, 6,
2275         1, 0, 2, 1, 2, 3,
2276 };
2277
2278 static const float bboxpoints[8][3] =
2279 {
2280         {-1,-1,-1},
2281         { 1,-1,-1},
2282         {-1, 1,-1},
2283         { 1, 1,-1},
2284         {-1,-1, 1},
2285         { 1,-1, 1},
2286         {-1, 1, 1},
2287         { 1, 1, 1},
2288 };
2289
2290 void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadowmapping)
2291 {
2292         int i;
2293         float vertex3f[8*3];
2294         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
2295         CHECKGLERROR
2296         R_Shadow_RenderMode_Reset();
2297         r_shadow_rendermode = r_shadow_lightingrendermode;
2298         // do global setup needed for the chosen lighting mode
2299         {
2300                 R_EntityMatrix(&identitymatrix);
2301                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2302                 if (stenciltest)
2303                 {
2304                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2305                         // only draw light where this geometry was already rendered AND the
2306                         // stencil is 128 (values other than this mean shadow)
2307                         qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
2308                 }
2309                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
2310                 if (shadowmapping)
2311                 {
2312                         if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2313                                 r_shadow_usingshadowmap2d = true;
2314                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2315                                 r_shadow_usingshadowmaprect = true;
2316                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2317                                 r_shadow_usingshadowmapcube = true;
2318                 }
2319
2320                 // render the lighting
2321                 R_SetupShader_DeferredLight(rsurface.rtlight);
2322                 for (i = 0;i < 8;i++)
2323                         Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
2324                 CHECKGLERROR
2325                 R_Mesh_VertexPointer(vertex3f, 0, 0);
2326                 R_Mesh_ColorPointer(NULL, 0, 0);
2327                 GL_ColorMask(1,1,1,1);
2328                 GL_DepthMask(false);
2329                 GL_DepthRange(0, 1);
2330                 GL_PolygonOffset(0, 0);
2331                 GL_DepthTest(true);
2332                 qglDepthFunc(GL_GREATER);CHECKGLERROR
2333                 GL_CullFace(r_refdef.view.cullface_back);
2334                 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
2335         }
2336 }
2337
2338 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
2339 {
2340         CHECKGLERROR
2341         R_Shadow_RenderMode_Reset();
2342         GL_BlendFunc(GL_ONE, GL_ONE);
2343         GL_DepthRange(0, 1);
2344         GL_DepthTest(r_showshadowvolumes.integer < 2);
2345         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
2346         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2347         GL_CullFace(GL_NONE);
2348         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
2349 }
2350
2351 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
2352 {
2353         CHECKGLERROR
2354         R_Shadow_RenderMode_Reset();
2355         GL_BlendFunc(GL_ONE, GL_ONE);
2356         GL_DepthRange(0, 1);
2357         GL_DepthTest(r_showlighting.integer < 2);
2358         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2359         if (!transparent)
2360         {
2361                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2362         }
2363         if (stenciltest)
2364         {
2365                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2366                 qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
2367         }
2368         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2369 }
2370
2371 void R_Shadow_RenderMode_End(void)
2372 {
2373         CHECKGLERROR
2374         R_Shadow_RenderMode_Reset();
2375         R_Shadow_RenderMode_ActiveLight(NULL);
2376         GL_DepthMask(true);
2377         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2378         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2379 }
2380
2381 int bboxedges[12][2] =
2382 {
2383         // top
2384         {0, 1}, // +X
2385         {0, 2}, // +Y
2386         {1, 3}, // Y, +X
2387         {2, 3}, // X, +Y
2388         // bottom
2389         {4, 5}, // +X
2390         {4, 6}, // +Y
2391         {5, 7}, // Y, +X
2392         {6, 7}, // X, +Y
2393         // verticals
2394         {0, 4}, // +Z
2395         {1, 5}, // X, +Z
2396         {2, 6}, // Y, +Z
2397         {3, 7}, // XY, +Z
2398 };
2399
2400 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2401 {
2402         int i, ix1, iy1, ix2, iy2;
2403         float x1, y1, x2, y2;
2404         vec4_t v, v2;
2405         float vertex[20][3];
2406         int j, k;
2407         vec4_t plane4f;
2408         int numvertices;
2409         float corner[8][4];
2410         float dist[8];
2411         int sign[8];
2412         float f;
2413
2414         r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2415         r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2416         r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2417         r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2418
2419         if (!r_shadow_scissor.integer)
2420                 return false;
2421
2422         // if view is inside the light box, just say yes it's visible
2423         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
2424                 return false;
2425
2426         x1 = y1 = x2 = y2 = 0;
2427
2428         // transform all corners that are infront of the nearclip plane
2429         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
2430         plane4f[3] = r_refdef.view.frustum[4].dist;
2431         numvertices = 0;
2432         for (i = 0;i < 8;i++)
2433         {
2434                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
2435                 dist[i] = DotProduct4(corner[i], plane4f);
2436                 sign[i] = dist[i] > 0;
2437                 if (!sign[i])
2438                 {
2439                         VectorCopy(corner[i], vertex[numvertices]);
2440                         numvertices++;
2441                 }
2442         }
2443         // if some points are behind the nearclip, add clipped edge points to make
2444         // sure that the scissor boundary is complete
2445         if (numvertices > 0 && numvertices < 8)
2446         {
2447                 // add clipped edge points
2448                 for (i = 0;i < 12;i++)
2449                 {
2450                         j = bboxedges[i][0];
2451                         k = bboxedges[i][1];
2452                         if (sign[j] != sign[k])
2453                         {
2454                                 f = dist[j] / (dist[j] - dist[k]);
2455                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
2456                                 numvertices++;
2457                         }
2458                 }
2459         }
2460
2461         // if we have no points to check, the light is behind the view plane
2462         if (!numvertices)
2463                 return true;
2464
2465         // if we have some points to transform, check what screen area is covered
2466         x1 = y1 = x2 = y2 = 0;
2467         v[3] = 1.0f;
2468         //Con_Printf("%i vertices to transform...\n", numvertices);
2469         for (i = 0;i < numvertices;i++)
2470         {
2471                 VectorCopy(vertex[i], v);
2472                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
2473                 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
2474                 if (i)
2475                 {
2476                         if (x1 > v2[0]) x1 = v2[0];
2477                         if (x2 < v2[0]) x2 = v2[0];
2478                         if (y1 > v2[1]) y1 = v2[1];
2479                         if (y2 < v2[1]) y2 = v2[1];
2480                 }
2481                 else
2482                 {
2483                         x1 = x2 = v2[0];
2484                         y1 = y2 = v2[1];
2485                 }
2486         }
2487
2488         // now convert the scissor rectangle to integer screen coordinates
2489         ix1 = (int)(x1 - 1.0f);
2490         iy1 = vid.height - (int)(y2 - 1.0f);
2491         ix2 = (int)(x2 + 1.0f);
2492         iy2 = vid.height - (int)(y1 + 1.0f);
2493         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
2494
2495         // clamp it to the screen
2496         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
2497         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
2498         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
2499         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
2500
2501         // if it is inside out, it's not visible
2502         if (ix2 <= ix1 || iy2 <= iy1)
2503                 return true;
2504
2505         // the light area is visible, set up the scissor rectangle
2506         r_shadow_lightscissor[0] = ix1;
2507         r_shadow_lightscissor[1] = iy1;
2508         r_shadow_lightscissor[2] = ix2 - ix1;
2509         r_shadow_lightscissor[3] = iy2 - iy1;
2510
2511         r_refdef.stats.lights_scissored++;
2512         return false;
2513 }
2514
2515 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
2516 {
2517         const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
2518         const float *normal3f = rsurface.normal3f + 3 * firstvertex;
2519         float *color4f = rsurface.array_color4f + 4 * firstvertex;
2520         float dist, dot, distintensity, shadeintensity, v[3], n[3];
2521         switch (r_shadow_rendermode)
2522         {
2523         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2524         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2525                 if (VectorLength2(diffusecolor) > 0)
2526                 {
2527                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2528                         {
2529                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2530                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2531                                 if ((dot = DotProduct(n, v)) < 0)
2532                                 {
2533                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2534                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
2535                                 }
2536                                 else
2537                                         VectorCopy(ambientcolor, color4f);
2538                                 if (r_refdef.fogenabled)
2539                                 {
2540                                         float f;
2541                                         f = RSurf_FogVertex(vertex3f);
2542                                         VectorScale(color4f, f, color4f);
2543                                 }
2544                                 color4f[3] = 1;
2545                         }
2546                 }
2547                 else
2548                 {
2549                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2550                         {
2551                                 VectorCopy(ambientcolor, color4f);
2552                                 if (r_refdef.fogenabled)
2553                                 {
2554                                         float f;
2555                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2556                                         f = RSurf_FogVertex(vertex3f);
2557                                         VectorScale(color4f, f, color4f);
2558                                 }
2559                                 color4f[3] = 1;
2560                         }
2561                 }
2562                 break;
2563         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2564                 if (VectorLength2(diffusecolor) > 0)
2565                 {
2566                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2567                         {
2568                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2569                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2570                                 {
2571                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2572                                         if ((dot = DotProduct(n, v)) < 0)
2573                                         {
2574                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2575                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2576                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2577                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2578                                         }
2579                                         else
2580                                         {
2581                                                 color4f[0] = ambientcolor[0] * distintensity;
2582                                                 color4f[1] = ambientcolor[1] * distintensity;
2583                                                 color4f[2] = ambientcolor[2] * distintensity;
2584                                         }
2585                                         if (r_refdef.fogenabled)
2586                                         {
2587                                                 float f;
2588                                                 f = RSurf_FogVertex(vertex3f);
2589                                                 VectorScale(color4f, f, color4f);
2590                                         }
2591                                 }
2592                                 else
2593                                         VectorClear(color4f);
2594                                 color4f[3] = 1;
2595                         }
2596                 }
2597                 else
2598                 {
2599                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2600                         {
2601                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2602                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2603                                 {
2604                                         color4f[0] = ambientcolor[0] * distintensity;
2605                                         color4f[1] = ambientcolor[1] * distintensity;
2606                                         color4f[2] = ambientcolor[2] * distintensity;
2607                                         if (r_refdef.fogenabled)
2608                                         {
2609                                                 float f;
2610                                                 f = RSurf_FogVertex(vertex3f);
2611                                                 VectorScale(color4f, f, color4f);
2612                                         }
2613                                 }
2614                                 else
2615                                         VectorClear(color4f);
2616                                 color4f[3] = 1;
2617                         }
2618                 }
2619                 break;
2620         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2621                 if (VectorLength2(diffusecolor) > 0)
2622                 {
2623                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2624                         {
2625                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2626                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2627                                 {
2628                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2629                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2630                                         if ((dot = DotProduct(n, v)) < 0)
2631                                         {
2632                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2633                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2634                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2635                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2636                                         }
2637                                         else
2638                                         {
2639                                                 color4f[0] = ambientcolor[0] * distintensity;
2640                                                 color4f[1] = ambientcolor[1] * distintensity;
2641                                                 color4f[2] = ambientcolor[2] * distintensity;
2642                                         }
2643                                         if (r_refdef.fogenabled)
2644                                         {
2645                                                 float f;
2646                                                 f = RSurf_FogVertex(vertex3f);
2647                                                 VectorScale(color4f, f, color4f);
2648                                         }
2649                                 }
2650                                 else
2651                                         VectorClear(color4f);
2652                                 color4f[3] = 1;
2653                         }
2654                 }
2655                 else
2656                 {
2657                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2658                         {
2659                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2660                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2661                                 {
2662                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2663                                         color4f[0] = ambientcolor[0] * distintensity;
2664                                         color4f[1] = ambientcolor[1] * distintensity;
2665                                         color4f[2] = ambientcolor[2] * distintensity;
2666                                         if (r_refdef.fogenabled)
2667                                         {
2668                                                 float f;
2669                                                 f = RSurf_FogVertex(vertex3f);
2670                                                 VectorScale(color4f, f, color4f);
2671                                         }
2672                                 }
2673                                 else
2674                                         VectorClear(color4f);
2675                                 color4f[3] = 1;
2676                         }
2677                 }
2678                 break;
2679         default:
2680                 break;
2681         }
2682 }
2683
2684 static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
2685 {
2686         // used to display how many times a surface is lit for level design purposes
2687         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2688 }
2689
2690 static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
2691 {
2692         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2693         R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT);
2694         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2695         {
2696                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2697         }
2698         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2699         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2700         {
2701                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2702         }
2703 }
2704
2705 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
2706 {
2707         int renders;
2708         int i;
2709         int stop;
2710         int newfirstvertex;
2711         int newlastvertex;
2712         int newnumtriangles;
2713         int *newe;
2714         const int *e;
2715         float *c;
2716         int maxtriangles = 4096;
2717         static int newelements[4096*3];
2718         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2);
2719         for (renders = 0;renders < 64;renders++)
2720         {
2721                 stop = true;
2722                 newfirstvertex = 0;
2723                 newlastvertex = 0;
2724                 newnumtriangles = 0;
2725                 newe = newelements;
2726                 // due to low fillrate on the cards this vertex lighting path is
2727                 // designed for, we manually cull all triangles that do not
2728                 // contain a lit vertex
2729                 // this builds batches of triangles from multiple surfaces and
2730                 // renders them at once
2731                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
2732                 {
2733                         if (VectorLength2(rsurface.array_color4f + e[0] * 4) + VectorLength2(rsurface.array_color4f + e[1] * 4) + VectorLength2(rsurface.array_color4f + e[2] * 4) >= 0.01)
2734                         {
2735                                 if (newnumtriangles)
2736                                 {
2737                                         newfirstvertex = min(newfirstvertex, e[0]);
2738                                         newlastvertex  = max(newlastvertex, e[0]);
2739                                 }
2740                                 else
2741                                 {
2742                                         newfirstvertex = e[0];
2743                                         newlastvertex = e[0];
2744                                 }
2745                                 newfirstvertex = min(newfirstvertex, e[1]);
2746                                 newlastvertex  = max(newlastvertex, e[1]);
2747                                 newfirstvertex = min(newfirstvertex, e[2]);
2748                                 newlastvertex  = max(newlastvertex, e[2]);
2749                                 newe[0] = e[0];
2750                                 newe[1] = e[1];
2751                                 newe[2] = e[2];
2752                                 newnumtriangles++;
2753                                 newe += 3;
2754                                 if (newnumtriangles >= maxtriangles)
2755                                 {
2756                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2757                                         newnumtriangles = 0;
2758                                         newe = newelements;
2759                                         stop = false;
2760                                 }
2761                         }
2762                 }
2763                 if (newnumtriangles >= 1)
2764                 {
2765                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2766                         stop = false;
2767                 }
2768                 // if we couldn't find any lit triangles, exit early
2769                 if (stop)
2770                         break;
2771                 // now reduce the intensity for the next overbright pass
2772                 // we have to clamp to 0 here incase the drivers have improper
2773                 // handling of negative colors
2774                 // (some old drivers even have improper handling of >1 color)
2775                 stop = true;
2776                 for (i = 0, c = rsurface.array_color4f + 4 * firstvertex;i < numvertices;i++, c += 4)
2777                 {
2778                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
2779                         {
2780                                 c[0] = max(0, c[0] - 1);
2781                                 c[1] = max(0, c[1] - 1);
2782                                 c[2] = max(0, c[2] - 1);
2783                                 stop = false;
2784                         }
2785                         else
2786                                 VectorClear(c);
2787                 }
2788                 // another check...
2789                 if (stop)
2790                         break;
2791         }
2792 }
2793
2794 static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, const vec3_t lightcolor, float ambientscale, float diffusescale)
2795 {
2796         // OpenGL 1.1 path (anything)
2797         float ambientcolorbase[3], diffusecolorbase[3];
2798         float ambientcolorpants[3], diffusecolorpants[3];
2799         float ambientcolorshirt[3], diffusecolorshirt[3];
2800         const float *surfacecolor = rsurface.texture->dlightcolor;
2801         const float *surfacepants = rsurface.colormap_pantscolor;
2802         const float *surfaceshirt = rsurface.colormap_shirtcolor;
2803         rtexture_t *basetexture = rsurface.texture->basetexture;
2804         rtexture_t *pantstexture = rsurface.texture->pantstexture;
2805         rtexture_t *shirttexture = rsurface.texture->shirttexture;
2806         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
2807         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
2808         ambientscale *= 2 * r_refdef.view.colorscale;
2809         diffusescale *= 2 * r_refdef.view.colorscale;
2810         ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
2811         diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
2812         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
2813         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
2814         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
2815         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
2816         R_Mesh_TexBind(0, basetexture);
2817         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
2818         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2819         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
2820         switch(r_shadow_rendermode)
2821         {
2822         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2823                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
2824                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2825                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2826                 R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2827                 break;
2828         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2829                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
2830                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
2831                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
2832                 R_Mesh_TexCoordPointer(2, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2833                 // fall through
2834         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2835                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
2836                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2837                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2838                 R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2839                 break;
2840         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2841                 break;
2842         default:
2843                 break;
2844         }
2845         //R_Mesh_TexBind(0, basetexture);
2846         R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase);
2847         if (dopants)
2848         {
2849                 R_Mesh_TexBind(0, pantstexture);
2850                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants);
2851         }
2852         if (doshirt)
2853         {
2854                 R_Mesh_TexBind(0, shirttexture);
2855                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt);
2856         }
2857 }
2858
2859 extern cvar_t gl_lightmaps;
2860 void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
2861 {
2862         float ambientscale, diffusescale, specularscale;
2863         qboolean negated;
2864         float lightcolor[3];
2865         VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
2866         ambientscale = rsurface.rtlight->ambientscale;
2867         diffusescale = rsurface.rtlight->diffusescale;
2868         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
2869         if (!r_shadow_usenormalmap.integer)
2870         {
2871                 ambientscale += 1.0f * diffusescale;
2872                 diffusescale = 0;
2873                 specularscale = 0;
2874         }
2875         if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
2876                 return;
2877         negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
2878         if(negated)
2879         {
2880                 VectorNegate(lightcolor, lightcolor);
2881                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2882         }
2883         RSurf_SetupDepthAndCulling();
2884         switch (r_shadow_rendermode)
2885         {
2886         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
2887                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
2888                 R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2889                 break;
2890         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
2891                 R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolor, ambientscale, diffusescale, specularscale);
2892                 break;
2893         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2894         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2895         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2896         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2897                 R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolor, ambientscale, diffusescale);
2898                 break;
2899         default:
2900                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2901                 break;
2902         }
2903         if(negated)
2904                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2905 }
2906
2907 void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
2908 {
2909         matrix4x4_t tempmatrix = *matrix;
2910         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
2911
2912         // if this light has been compiled before, free the associated data
2913         R_RTLight_Uncompile(rtlight);
2914
2915         // clear it completely to avoid any lingering data
2916         memset(rtlight, 0, sizeof(*rtlight));
2917
2918         // copy the properties
2919         rtlight->matrix_lighttoworld = tempmatrix;
2920         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
2921         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
2922         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
2923         VectorCopy(color, rtlight->color);
2924         rtlight->cubemapname[0] = 0;
2925         if (cubemapname && cubemapname[0])
2926                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
2927         rtlight->shadow = shadow;
2928         rtlight->corona = corona;
2929         rtlight->style = style;
2930         rtlight->isstatic = isstatic;
2931         rtlight->coronasizescale = coronasizescale;
2932         rtlight->ambientscale = ambientscale;
2933         rtlight->diffusescale = diffusescale;
2934         rtlight->specularscale = specularscale;
2935         rtlight->flags = flags;
2936
2937         // compute derived data
2938         //rtlight->cullradius = rtlight->radius;
2939         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
2940         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2941         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2942         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2943         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2944         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2945         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2946 }
2947
2948 // compiles rtlight geometry
2949 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
2950 void R_RTLight_Compile(rtlight_t *rtlight)
2951 {
2952         int i;
2953         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
2954         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
2955         entity_render_t *ent = r_refdef.scene.worldentity;
2956         dp_model_t *model = r_refdef.scene.worldmodel;
2957         unsigned char *data;
2958         shadowmesh_t *mesh;
2959
2960         // compile the light
2961         rtlight->compiled = true;
2962         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
2963         rtlight->static_numleafs = 0;
2964         rtlight->static_numleafpvsbytes = 0;
2965         rtlight->static_leaflist = NULL;
2966         rtlight->static_leafpvs = NULL;
2967         rtlight->static_numsurfaces = 0;
2968         rtlight->static_surfacelist = NULL;
2969         rtlight->static_shadowmap_receivers = 0x3F;
2970         rtlight->static_shadowmap_casters = 0x3F;
2971         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2972         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2973         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2974         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2975         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2976         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2977
2978         if (model && model->GetLightInfo)
2979         {
2980                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
2981                 r_shadow_compilingrtlight = rtlight;
2982                 model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs, 0, NULL);
2983                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
2984                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
2985                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
2986                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
2987                 rtlight->static_numsurfaces = numsurfaces;
2988                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
2989                 rtlight->static_numleafs = numleafs;
2990                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
2991                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
2992                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
2993                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
2994                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
2995                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
2996                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
2997                 if (rtlight->static_numsurfaces)
2998                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
2999                 if (rtlight->static_numleafs)
3000                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3001                 if (rtlight->static_numleafpvsbytes)
3002                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
3003                 if (rtlight->static_numshadowtrispvsbytes)
3004                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
3005                 if (rtlight->static_numlighttrispvsbytes)
3006                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
3007                 switch (rtlight->shadowmode)
3008                 {
3009                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
3010                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
3011                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
3012                         if (model->CompileShadowMap && rtlight->shadow)
3013                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3014                         break;
3015                 default:
3016                         if (model->CompileShadowVolume && rtlight->shadow)
3017                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3018                         break;
3019                 }
3020                 // now we're done compiling the rtlight
3021                 r_shadow_compilingrtlight = NULL;
3022         }
3023
3024
3025         // use smallest available cullradius - box radius or light radius
3026         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
3027         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
3028
3029         shadowzpasstris = 0;
3030         if (rtlight->static_meshchain_shadow_zpass)
3031                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
3032                         shadowzpasstris += mesh->numtriangles;
3033
3034         shadowzfailtris = 0;
3035         if (rtlight->static_meshchain_shadow_zfail)
3036                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
3037                         shadowzfailtris += mesh->numtriangles;
3038
3039         lighttris = 0;
3040         if (rtlight->static_numlighttrispvsbytes)
3041                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
3042                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
3043                                 lighttris++;
3044
3045         shadowtris = 0;
3046         if (rtlight->static_numlighttrispvsbytes)
3047                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
3048                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
3049                                 shadowtris++;
3050
3051         if (developer_extra.integer)
3052                 Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
3053 }
3054
3055 void R_RTLight_Uncompile(rtlight_t *rtlight)
3056 {
3057         if (rtlight->compiled)
3058         {
3059                 if (rtlight->static_meshchain_shadow_zpass)
3060                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
3061                 rtlight->static_meshchain_shadow_zpass = NULL;
3062                 if (rtlight->static_meshchain_shadow_zfail)
3063                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
3064                 rtlight->static_meshchain_shadow_zfail = NULL;
3065                 if (rtlight->static_meshchain_shadow_shadowmap)
3066                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
3067                 rtlight->static_meshchain_shadow_shadowmap = NULL;
3068                 // these allocations are grouped
3069                 if (rtlight->static_surfacelist)
3070                         Mem_Free(rtlight->static_surfacelist);
3071                 rtlight->static_numleafs = 0;
3072                 rtlight->static_numleafpvsbytes = 0;
3073                 rtlight->static_leaflist = NULL;
3074                 rtlight->static_leafpvs = NULL;
3075                 rtlight->static_numsurfaces = 0;
3076                 rtlight->static_surfacelist = NULL;
3077                 rtlight->static_numshadowtrispvsbytes = 0;
3078                 rtlight->static_shadowtrispvs = NULL;
3079                 rtlight->static_numlighttrispvsbytes = 0;
3080                 rtlight->static_lighttrispvs = NULL;
3081                 rtlight->compiled = false;
3082         }
3083 }
3084
3085 void R_Shadow_UncompileWorldLights(void)
3086 {
3087         size_t lightindex;
3088         dlight_t *light;
3089         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3090         for (lightindex = 0;lightindex < range;lightindex++)
3091         {
3092                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3093                 if (!light)
3094                         continue;
3095                 R_RTLight_Uncompile(&light->rtlight);
3096         }
3097 }
3098
3099 void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
3100 {
3101         int i, j;
3102         mplane_t plane;
3103         // reset the count of frustum planes
3104         // see rtlight->cached_frustumplanes definition for how much this array
3105         // can hold
3106         rtlight->cached_numfrustumplanes = 0;
3107
3108         // haven't implemented a culling path for ortho rendering
3109         if (!r_refdef.view.useperspective)
3110         {
3111                 // check if the light is on screen and copy the 4 planes if it is
3112                 for (i = 0;i < 4;i++)
3113                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3114                                 break;
3115                 if (i == 4)
3116                         for (i = 0;i < 4;i++)
3117                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3118                 return;
3119         }
3120
3121 #if 1
3122         // generate a deformed frustum that includes the light origin, this is
3123         // used to cull shadow casting surfaces that can not possibly cast a
3124         // shadow onto the visible light-receiving surfaces, which can be a
3125         // performance gain
3126         //
3127         // if the light origin is onscreen the result will be 4 planes exactly
3128         // if the light origin is offscreen on only one axis the result will
3129         // be exactly 5 planes (split-side case)
3130         // if the light origin is offscreen on two axes the result will be
3131         // exactly 4 planes (stretched corner case)
3132         for (i = 0;i < 4;i++)
3133         {
3134                 // quickly reject standard frustum planes that put the light
3135                 // origin outside the frustum
3136                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3137                         continue;
3138                 // copy the plane
3139                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3140         }
3141         // if all the standard frustum planes were accepted, the light is onscreen
3142         // otherwise we need to generate some more planes below...
3143         if (rtlight->cached_numfrustumplanes < 4)
3144         {
3145                 // at least one of the stock frustum planes failed, so we need to
3146                 // create one or two custom planes to enclose the light origin
3147                 for (i = 0;i < 4;i++)
3148                 {
3149                         // create a plane using the view origin and light origin, and a
3150                         // single point from the frustum corner set
3151                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
3152                         VectorNormalize(plane.normal);
3153                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
3154                         // see if this plane is backwards and flip it if so
3155                         for (j = 0;j < 4;j++)
3156                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3157                                         break;
3158                         if (j < 4)
3159                         {
3160                                 VectorNegate(plane.normal, plane.normal);
3161                                 plane.dist *= -1;
3162                                 // flipped plane, test again to see if it is now valid
3163                                 for (j = 0;j < 4;j++)
3164                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3165                                                 break;
3166                                 // if the plane is still not valid, then it is dividing the
3167                                 // frustum and has to be rejected
3168                                 if (j < 4)
3169                                         continue;
3170                         }
3171                         // we have created a valid plane, compute extra info
3172                         PlaneClassify(&plane);
3173                         // copy the plane
3174                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3175 #if 1
3176                         // if we've found 5 frustum planes then we have constructed a
3177                         // proper split-side case and do not need to keep searching for
3178                         // planes to enclose the light origin
3179                         if (rtlight->cached_numfrustumplanes == 5)
3180                                 break;
3181 #endif
3182                 }
3183         }
3184 #endif
3185
3186 #if 0
3187         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
3188         {
3189                 plane = rtlight->cached_frustumplanes[i];
3190                 Con_Printf("light %p plane #%i %f %f %f : %f (%f %f %f %f %f)\n", rtlight, i, plane.normal[0], plane.normal[1], plane.normal[2], plane.dist, PlaneDiff(r_refdef.view.frustumcorner[0], &plane), PlaneDiff(r_refdef.view.frustumcorner[1], &plane), PlaneDiff(r_refdef.view.frustumcorner[2], &plane), PlaneDiff(r_refdef.view.frustumcorner[3], &plane), PlaneDiff(rtlight->shadoworigin, &plane));
3191         }
3192 #endif
3193
3194 #if 0
3195         // now add the light-space box planes if the light box is rotated, as any
3196         // caster outside the oriented light box is irrelevant (even if it passed
3197         // the worldspace light box, which is axial)
3198         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
3199         {
3200                 for (i = 0;i < 6;i++)
3201                 {
3202                         vec3_t v;
3203                         VectorClear(v);
3204                         v[i >> 1] = (i & 1) ? -1 : 1;
3205                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
3206                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
3207                         plane.dist = VectorNormalizeLength(plane.normal);
3208                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
3209                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3210                 }
3211         }
3212 #endif
3213
3214 #if 0
3215         // add the world-space reduced box planes
3216         for (i = 0;i < 6;i++)
3217         {
3218                 VectorClear(plane.normal);
3219                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
3220                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
3221                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3222         }
3223 #endif
3224
3225 #if 0
3226         {
3227         int j, oldnum;
3228         vec3_t points[8];
3229         vec_t bestdist;
3230         // reduce all plane distances to tightly fit the rtlight cull box, which
3231         // is in worldspace
3232         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3233         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3234         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3235         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3236         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3237         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3238         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3239         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3240         oldnum = rtlight->cached_numfrustumplanes;
3241         rtlight->cached_numfrustumplanes = 0;
3242         for (j = 0;j < oldnum;j++)
3243         {
3244                 // find the nearest point on the box to this plane
3245                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
3246                 for (i = 1;i < 8;i++)
3247                 {
3248                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
3249                         if (bestdist > dist)
3250                                 bestdist = dist;
3251                 }
3252                 Con_Printf("light %p %splane #%i %f %f %f : %f < %f\n", rtlight, rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125 ? "^2" : "^1", j, rtlight->cached_frustumplanes[j].normal[0], rtlight->cached_frustumplanes[j].normal[1], rtlight->cached_frustumplanes[j].normal[2], rtlight->cached_frustumplanes[j].dist, bestdist);
3253                 // if the nearest point is near or behind the plane, we want this
3254                 // plane, otherwise the plane is useless as it won't cull anything
3255                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
3256                 {
3257                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
3258                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
3259                 }
3260         }
3261         }
3262 #endif
3263 }
3264
3265 void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
3266 {
3267         shadowmesh_t *mesh;
3268
3269         RSurf_ActiveWorldEntity();
3270
3271         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3272         {
3273                 CHECKGLERROR
3274                 GL_CullFace(GL_NONE);
3275         mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
3276         for (;mesh;mesh = mesh->next)
3277         {
3278                         if (!mesh->sidetotals[r_shadow_shadowmapside])
3279                                 continue;
3280             r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
3281             R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3282             R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3283         }
3284         CHECKGLERROR
3285     }
3286         else if (r_refdef.scene.worldentity->model)
3287                 r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3288
3289         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3290 }
3291
3292 void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
3293 {
3294         qboolean zpass = false;
3295         shadowmesh_t *mesh;
3296         int t, tend;
3297         int surfacelistindex;
3298         msurface_t *surface;
3299
3300         RSurf_ActiveWorldEntity();
3301
3302         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3303         {
3304                 CHECKGLERROR
3305                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
3306                 {
3307                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3308                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
3309                 }
3310                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
3311                 for (;mesh;mesh = mesh->next)
3312                 {
3313                         r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
3314                         R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3315                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
3316                         {
3317                                 // increment stencil if frontface is infront of depthbuffer
3318                                 GL_CullFace(r_refdef.view.cullface_back);
3319                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
3320                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3321                                 // decrement stencil if backface is infront of depthbuffer
3322                                 GL_CullFace(r_refdef.view.cullface_front);
3323                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
3324                         }
3325                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
3326                         {
3327                                 // decrement stencil if backface is behind depthbuffer
3328                                 GL_CullFace(r_refdef.view.cullface_front);
3329                                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
3330                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3331                                 // increment stencil if frontface is behind depthbuffer
3332                                 GL_CullFace(r_refdef.view.cullface_back);
3333                                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
3334                         }
3335                         R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3336                 }
3337                 CHECKGLERROR
3338         }
3339         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
3340         {
3341                 // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
3342                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
3343                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3344                 {
3345                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
3346                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
3347                                 if (CHECKPVSBIT(trispvs, t))
3348                                         shadowmarklist[numshadowmark++] = t;
3349                 }
3350                 R_Shadow_VolumeFromList(r_refdef.scene.worldmodel->brush.shadowmesh->numverts, r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles, r_refdef.scene.worldmodel->brush.shadowmesh->vertex3f, r_refdef.scene.worldmodel->brush.shadowmesh->element3i, r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.scene.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist, r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3351         }
3352         else if (numsurfaces)
3353                 r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3354
3355         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3356 }
3357
3358 void R_Shadow_DrawEntityShadow(entity_render_t *ent)
3359 {
3360         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
3361         vec_t relativeshadowradius;
3362         RSurf_ActiveModelEntity(ent, false, false, false);
3363         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
3364         // we need to re-init the shader for each entity because the matrix changed
3365         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
3366         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
3367         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
3368         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
3369         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
3370         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
3371         relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
3372         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D)
3373         {
3374                 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
3375         }
3376         else
3377                 ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
3378         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3379 }
3380
3381 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
3382 {
3383         // set up properties for rendering light onto this entity
3384         RSurf_ActiveModelEntity(ent, true, true, false);
3385         GL_AlphaTest(false);
3386         Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
3387         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3388         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3389         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3390 }
3391
3392 void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
3393 {
3394         if (!r_refdef.scene.worldmodel->DrawLight)
3395                 return;
3396
3397         // set up properties for rendering light onto this entity
3398         RSurf_ActiveWorldEntity();
3399         GL_AlphaTest(false);
3400         rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
3401         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3402         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3403         VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3404
3405         r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
3406
3407         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3408 }
3409
3410 void R_Shadow_DrawEntityLight(entity_render_t *ent)
3411 {
3412         dp_model_t *model = ent->model;
3413         if (!model->DrawLight)
3414                 return;
3415
3416         R_Shadow_SetupEntityLight(ent);
3417
3418         model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
3419
3420         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3421 }
3422
3423 void R_Shadow_PrepareLight(rtlight_t *rtlight)
3424 {
3425         int i;
3426         float f;
3427         int numleafs, numsurfaces;
3428         int *leaflist, *surfacelist;
3429         unsigned char *leafpvs, *shadowtrispvs, *lighttrispvs, *surfacesides;
3430         int numlightentities;
3431         int numlightentities_noselfshadow;
3432         int numshadowentities;
3433         int numshadowentities_noselfshadow;
3434         static entity_render_t *lightentities[MAX_EDICTS];
3435         static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
3436         static entity_render_t *shadowentities[MAX_EDICTS];
3437         static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
3438
3439         rtlight->draw = false;
3440
3441         // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
3442         // skip lights that are basically invisible (color 0 0 0)
3443         if (VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f))
3444                 return;
3445
3446         // loading is done before visibility checks because loading should happen
3447         // all at once at the start of a level, not when it stalls gameplay.
3448         // (especially important to benchmarks)
3449         // compile light
3450         if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
3451         {
3452                 if (rtlight->compiled)
3453                         R_RTLight_Uncompile(rtlight);
3454                 R_RTLight_Compile(rtlight);
3455         }
3456
3457         // load cubemap
3458         rtlight->currentcubemap = rtlight->cubemapname[0] ? R_Shadow_Cubemap(rtlight->cubemapname) : r_texture_whitecube;
3459
3460         // look up the light style value at this time
3461         f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
3462         VectorScale(rtlight->color, f, rtlight->currentcolor);
3463         /*
3464         if (rtlight->selected)
3465         {
3466                 f = 2 + sin(realtime * M_PI * 4.0);
3467                 VectorScale(rtlight->currentcolor, f, rtlight->currentcolor);
3468         }
3469         */
3470
3471         // if lightstyle is currently off, don't draw the light
3472         if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
3473                 return;
3474
3475         // if the light box is offscreen, skip it
3476         if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
3477                 return;
3478
3479         VectorCopy(rtlight->cullmins, rtlight->cached_cullmins);
3480         VectorCopy(rtlight->cullmaxs, rtlight->cached_cullmaxs);
3481
3482         R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
3483
3484         if (rtlight->compiled && r_shadow_realtime_world_compile.integer)
3485         {
3486                 // compiled light, world available and can receive realtime lighting
3487                 // retrieve leaf information
3488                 numleafs = rtlight->static_numleafs;
3489                 leaflist = rtlight->static_leaflist;
3490                 leafpvs = rtlight->static_leafpvs;
3491                 numsurfaces = rtlight->static_numsurfaces;
3492                 surfacelist = rtlight->static_surfacelist;
3493                 surfacesides = NULL;
3494                 shadowtrispvs = rtlight->static_shadowtrispvs;
3495                 lighttrispvs = rtlight->static_lighttrispvs;
3496         }
3497         else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->GetLightInfo)
3498         {
3499                 // dynamic light, world available and can receive realtime lighting
3500                 // calculate lit surfaces and leafs
3501                 r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rtlight->cached_cullmins, rtlight->cached_cullmaxs, r_shadow_buffer_leaflist, r_sh