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