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