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