added R_FrameData_Alloc and Store functions (a per-frame heap allocator
[divverent/darkplaces.git] / r_shadow.c
1
2 /*
3 Terminology: Stencil Shadow Volume (sometimes called Stencil Shadows)
4 An extrusion of the lit faces, beginning at the original geometry and ending
5 further from the light source than the original geometry (presumably at least
6 as far as the light's radius, if the light has a radius at all), capped at
7 both front and back to avoid any problems (extrusion from dark faces also
8 works but has a different set of problems)
9
10 This is normally rendered using Carmack's Reverse technique, in which
11 backfaces behind zbuffer (zfail) increment the stencil, and frontfaces behind
12 zbuffer (zfail) decrement the stencil, the result is a stencil value of zero
13 where shadows did not intersect the visible geometry, suitable as a stencil
14 mask for rendering lighting everywhere but shadow.
15
16 In our case to hopefully avoid the Creative Labs patent, we draw the backfaces
17 as decrement and the frontfaces as increment, and we redefine the DepthFunc to
18 GL_LESS (the patent uses GL_GEQUAL) which causes zfail when behind surfaces
19 and zpass when infront (the patent draws where zpass with a GL_GEQUAL test),
20 additionally we clear stencil to 128 to avoid the need for the unclamped
21 incr/decr extension (not related to patent).
22
23 Patent warning:
24 This algorithm may be covered by Creative's patent (US Patent #6384822),
25 however that patent is quite specific about increment on backfaces and
26 decrement on frontfaces where zpass with GL_GEQUAL depth test, which is
27 opposite this implementation and partially opposite Carmack's Reverse paper
28 (which uses GL_LESS, but increments on backfaces and decrements on frontfaces).
29
30
31
32 Terminology: Stencil Light Volume (sometimes called Light Volumes)
33 Similar to a Stencil Shadow Volume, but inverted; rather than containing the
34 areas in shadow it contains the areas in light, this can only be built
35 quickly for certain limited cases (such as portal visibility from a point),
36 but is quite useful for some effects (sunlight coming from sky polygons is
37 one possible example, translucent occluders is another example).
38
39
40
41 Terminology: Optimized Stencil Shadow Volume
42 A Stencil Shadow Volume that has been processed sufficiently to ensure it has
43 no duplicate coverage of areas (no need to shadow an area twice), often this
44 greatly improves performance but is an operation too costly to use on moving
45 lights (however completely optimal Stencil Light Volumes can be constructed
46 in some ideal cases).
47
48
49
50 Terminology: Per Pixel Lighting (sometimes abbreviated PPL)
51 Per pixel evaluation of lighting equations, at a bare minimum this involves
52 DOT3 shading of diffuse lighting (per pixel dotproduct of negated incidence
53 vector and surface normal, using a texture of the surface bumps, called a
54 NormalMap) if supported by hardware; in our case there is support for cards
55 which are incapable of DOT3, the quality is quite poor however.  Additionally
56 it is desirable to have specular evaluation per pixel, per vertex
57 normalization of specular halfangle vectors causes noticable distortion but
58 is unavoidable on hardware without GL_ARB_fragment_program or
59 GL_ARB_fragment_shader.
60
61
62
63 Terminology: Normalization CubeMap
64 A cubemap containing normalized dot3-encoded (vectors of length 1 or less
65 encoded as RGB colors) for any possible direction, this technique allows per
66 pixel calculation of incidence vector for per pixel lighting purposes, which
67 would not otherwise be possible per pixel without GL_ARB_fragment_program or
68 GL_ARB_fragment_shader.
69
70
71
72 Terminology: 2D+1D Attenuation Texturing
73 A very crude approximation of light attenuation with distance which results
74 in cylindrical light shapes which fade vertically as a streak (some games
75 such as Doom3 allow this to be rotated to be less noticable in specific
76 cases), the technique is simply modulating lighting by two 2D textures (which
77 can be the same) on different axes of projection (XY and Z, typically), this
78 is the second best technique available without 3D Attenuation Texturing,
79 GL_ARB_fragment_program or GL_ARB_fragment_shader technology.
80
81
82
83 Terminology: 2D+1D Inverse Attenuation Texturing
84 A clever method described in papers on the Abducted engine, this has a squared
85 distance texture (bright on the outside, black in the middle), which is used
86 twice using GL_ADD blending, the result of this is used in an inverse modulate
87 (GL_ONE_MINUS_DST_ALPHA, GL_ZERO) to implement the equation
88 lighting*=(1-((X*X+Y*Y)+(Z*Z))) which is spherical (unlike 2D+1D attenuation
89 texturing).
90
91
92
93 Terminology: 3D Attenuation Texturing
94 A slightly crude approximation of light attenuation with distance, its flaws
95 are limited radius and resolution (performance tradeoffs).
96
97
98
99 Terminology: 3D Attenuation-Normalization Texturing
100 A 3D Attenuation Texture merged with a Normalization CubeMap, by making the
101 vectors shorter the lighting becomes darker, a very effective optimization of
102 diffuse lighting if 3D Attenuation Textures are already used.
103
104
105
106 Terminology: Light Cubemap Filtering
107 A technique for modeling non-uniform light distribution according to
108 direction, for example a lantern may use a cubemap to describe the light
109 emission pattern of the cage around the lantern (as well as soot buildup
110 discoloring the light in certain areas), often also used for softened grate
111 shadows and light shining through a stained glass window (done crudely by
112 texturing the lighting with a cubemap), another good example would be a disco
113 light.  This technique is used heavily in many games (Doom3 does not support
114 this however).
115
116
117
118 Terminology: Light Projection Filtering
119 A technique for modeling shadowing of light passing through translucent
120 surfaces, allowing stained glass windows and other effects to be done more
121 elegantly than possible with Light Cubemap Filtering by applying an occluder
122 texture to the lighting combined with a stencil light volume to limit the lit
123 area, this technique is used by Doom3 for spotlights and flashlights, among
124 other things, this can also be used more generally to render light passing
125 through multiple translucent occluders in a scene (using a light volume to
126 describe the area beyond the occluder, and thus mask off rendering of all
127 other areas).
128
129
130
131 Terminology: Doom3 Lighting
132 A combination of Stencil Shadow Volume, Per Pixel Lighting, Normalization
133 CubeMap, 2D+1D Attenuation Texturing, and Light Projection Filtering, as
134 demonstrated by the game Doom3.
135 */
136
137 #include "quakedef.h"
138 #include "r_shadow.h"
139 #include "cl_collision.h"
140 #include "portals.h"
141 #include "image.h"
142
143 #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 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1293         {
1294                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1295                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1296                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1297         }
1298         else
1299         {
1300                 // decide which type of shadow to generate and set stencil mode
1301                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1302                 // generate the sides or a solid volume, depending on type
1303                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1304                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1305                 else
1306                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1307                 r_refdef.stats.lights_dynamicshadowtriangles += tris;
1308                 r_refdef.stats.lights_shadowtriangles += tris;
1309                 CHECKGLERROR
1310                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1311                 GL_LockArrays(0, outverts);
1312                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1313                 {
1314                         // increment stencil if frontface is infront of depthbuffer
1315                         GL_CullFace(r_refdef.view.cullface_front);
1316                         qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
1317                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1318                         // decrement stencil if backface is infront of depthbuffer
1319                         GL_CullFace(r_refdef.view.cullface_back);
1320                         qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
1321                 }
1322                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1323                 {
1324                         // decrement stencil if backface is behind depthbuffer
1325                         GL_CullFace(r_refdef.view.cullface_front);
1326                         qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
1327                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1328                         // increment stencil if frontface is behind depthbuffer
1329                         GL_CullFace(r_refdef.view.cullface_back);
1330                         qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
1331                 }
1332                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1333                 GL_LockArrays(0, 0);
1334                 CHECKGLERROR
1335         }
1336 }
1337
1338 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1339 {
1340     // p1, p2, p3 are in the cubemap's local coordinate system
1341     // bias = border/(size - border)
1342         int mask = 0x3F;
1343
1344     float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1345           dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1346           dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1347         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1348         mask &= (3<<4)
1349                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1350                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1351                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1352     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1353         mask &= (3<<4)
1354             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1355             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))            
1356             | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1357
1358     dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1359     dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1360     dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1361     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1362         mask &= (3<<0)
1363             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1364             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))            
1365             | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1366     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1367         mask &= (3<<0)
1368             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1369             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1370             | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1371
1372     dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1373     dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1374     dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1375     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1376         mask &= (3<<2)
1377             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1378             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1379             | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1380     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1381         mask &= (3<<2)
1382             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1383             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1384             | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1385
1386         return mask;
1387 }
1388
1389 int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1390 {
1391         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1392         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1393         int mask = 0x3F;
1394
1395         VectorSubtract(maxs, mins, radius);
1396     VectorScale(radius, 0.5f, radius);
1397     VectorAdd(mins, radius, center);
1398     Matrix4x4_Transform(worldtolight, center, lightcenter);
1399         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1400         VectorSubtract(lightcenter, lightradius, pmin);
1401         VectorAdd(lightcenter, lightradius, pmax);
1402
1403     dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1404     dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1405     if(ap1 > bias*an1 && ap2 > bias*an2)
1406         mask &= (3<<4)
1407             | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1408             | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1409     if(an1 > bias*ap1 && an2 > bias*ap2)
1410         mask &= (3<<4)
1411             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1412             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1413
1414     dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1415     dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1416     if(ap1 > bias*an1 && ap2 > bias*an2)
1417         mask &= (3<<0)
1418             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1419             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1420     if(an1 > bias*ap1 && an2 > bias*ap2)
1421         mask &= (3<<0)
1422             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1423             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1424
1425     dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1426     dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1427     if(ap1 > bias*an1 && ap2 > bias*an2)
1428         mask &= (3<<2)
1429             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1430             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1431     if(an1 > bias*ap1 && an2 > bias*ap2)
1432         mask &= (3<<2)
1433             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1434             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1435
1436     return mask;
1437 }
1438
1439 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1440
1441 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1442 {
1443     // p is in the cubemap's local coordinate system
1444     // bias = border/(size - border)
1445     float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1446     float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1447     float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1448     int mask = 0x3F;
1449     if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1450     if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1451     if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1452     if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1453     if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1454     if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1455     return mask;
1456 }
1457
1458 int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1459 {
1460         int i;
1461         vec3_t p, n;
1462         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1463         float scale = (size - 2*border)/size, len;
1464         float bias = border / (float)(size - border), dp, dn, ap, an;
1465         // check if cone enclosing side would cross frustum plane 
1466         scale = 2 / (scale*scale + 2);
1467         for (i = 0;i < 5;i++)
1468         {
1469                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
1470                         continue;
1471                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1472                 len = scale*VectorLength2(n);
1473                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1474                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1475                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1476         }
1477         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1478         {
1479         Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1480         len = scale*VectorLength(n);
1481                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1482                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1483                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1484         }
1485         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1486         // check if frustum corners/origin cross plane sides
1487         for (i = 0;i < 5;i++)
1488         {
1489                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1490                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
1491                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1492                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1493                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
1494                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1495                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1496                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
1497                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1498                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1499         }
1500         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1501 }
1502
1503 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)
1504 {
1505         int t, tend;
1506         const int *e;
1507         const float *v[3];
1508         float normal[3];
1509         vec3_t p[3];
1510         float bias;
1511         int mask, surfacemask = 0;
1512         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1513                 return 0;
1514         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1515         tend = firsttriangle + numtris;
1516         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1517         {
1518                 // surface box entirely inside light box, no box cull
1519                 if (projectdirection)
1520                 {
1521                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1522                         {
1523                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1524                                 TriangleNormal(v[0], v[1], v[2], normal);
1525                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1526                                 {
1527                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1528                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1529                                         surfacemask |= mask;
1530                                         if(totals)
1531                                         {
1532                                                 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;
1533                                                 shadowsides[numshadowsides] = mask;
1534                                                 shadowsideslist[numshadowsides++] = t;
1535                                         }
1536                                 }
1537                         }
1538                 }
1539                 else
1540                 {
1541                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1542                         {
1543                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1544                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1545                                 {
1546                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1547                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1548                                         surfacemask |= mask;
1549                                         if(totals)
1550                                         {
1551                                                 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;
1552                                                 shadowsides[numshadowsides] = mask;
1553                                                 shadowsideslist[numshadowsides++] = t;
1554                                         }
1555                                 }
1556                         }
1557                 }
1558         }
1559         else
1560         {
1561                 // surface box not entirely inside light box, cull each triangle
1562                 if (projectdirection)
1563                 {
1564                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1565                         {
1566                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1567                                 TriangleNormal(v[0], v[1], v[2], normal);
1568                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1569                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1570                                 {
1571                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1572                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1573                                         surfacemask |= mask;
1574                                         if(totals)
1575                                         {
1576                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1577                                                 shadowsides[numshadowsides] = mask;
1578                                                 shadowsideslist[numshadowsides++] = t;
1579                                         }
1580                                 }
1581                         }
1582                 }
1583                 else
1584                 {
1585                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1586                         {
1587                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1588                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1589                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1590                                 {
1591                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1592                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1593                                         surfacemask |= mask;
1594                                         if(totals)
1595                                         {
1596                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1597                                                 shadowsides[numshadowsides] = mask;
1598                                                 shadowsideslist[numshadowsides++] = t;
1599                                         }
1600                                 }
1601                         }
1602                 }
1603         }
1604         return surfacemask;
1605 }
1606
1607 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)
1608 {
1609         int i, j, outtriangles = 0;
1610         int *outelement3i[6];
1611         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1612                 return;
1613         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1614         // make sure shadowelements is big enough for this mesh
1615         if (maxshadowtriangles < outtriangles)
1616                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1617
1618         // compute the offset and size of the separate index lists for each cubemap side
1619         outtriangles = 0;
1620         for (i = 0;i < 6;i++)
1621         {
1622                 outelement3i[i] = shadowelements + outtriangles * 3;
1623                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1624                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1625                 outtriangles += sidetotals[i];
1626         }
1627
1628         // gather up the (sparse) triangles into separate index lists for each cubemap side
1629         for (i = 0;i < numsidetris;i++)
1630         {
1631                 const int *element = elements + sidetris[i] * 3;
1632                 for (j = 0;j < 6;j++)
1633                 {
1634                         if (sides[i] & (1 << j))
1635                         {
1636                                 outelement3i[j][0] = element[0];
1637                                 outelement3i[j][1] = element[1];
1638                                 outelement3i[j][2] = element[2];
1639                                 outelement3i[j] += 3;
1640                         }
1641                 }
1642         }
1643                         
1644         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1645 }
1646
1647 static void R_Shadow_MakeTextures_MakeCorona(void)
1648 {
1649         float dx, dy;
1650         int x, y, a;
1651         unsigned char pixels[32][32][4];
1652         for (y = 0;y < 32;y++)
1653         {
1654                 dy = (y - 15.5f) * (1.0f / 16.0f);
1655                 for (x = 0;x < 32;x++)
1656                 {
1657                         dx = (x - 15.5f) * (1.0f / 16.0f);
1658                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1659                         a = bound(0, a, 255);
1660                         pixels[y][x][0] = a;
1661                         pixels[y][x][1] = a;
1662                         pixels[y][x][2] = a;
1663                         pixels[y][x][3] = 255;
1664                 }
1665         }
1666         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_PRECACHE | TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
1667 }
1668
1669 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1670 {
1671         float dist = sqrt(x*x+y*y+z*z);
1672         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1673         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1674         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1675 }
1676
1677 static void R_Shadow_MakeTextures(void)
1678 {
1679         int x, y, z;
1680         float intensity, dist;
1681         unsigned int *data;
1682         R_Shadow_FreeShadowMaps();
1683         R_FreeTexturePool(&r_shadow_texturepool);
1684         r_shadow_texturepool = R_AllocTexturePool();
1685         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1686         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1687         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1688         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1689         for (x = 0;x <= ATTENTABLESIZE;x++)
1690         {
1691                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1692                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1693                 r_shadow_attentable[x] = bound(0, intensity, 1);
1694         }
1695         // 1D gradient texture
1696         for (x = 0;x < ATTEN1DSIZE;x++)
1697                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1698         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);
1699         // 2D circle texture
1700         for (y = 0;y < ATTEN2DSIZE;y++)
1701                 for (x = 0;x < ATTEN2DSIZE;x++)
1702                         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);
1703         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);
1704         // 3D sphere texture
1705         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1706         {
1707                 for (z = 0;z < ATTEN3DSIZE;z++)
1708                         for (y = 0;y < ATTEN3DSIZE;y++)
1709                                 for (x = 0;x < ATTEN3DSIZE;x++)
1710                                         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));
1711                 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);
1712         }
1713         else
1714                 r_shadow_attenuation3dtexture = NULL;
1715         Mem_Free(data);
1716
1717         R_Shadow_MakeTextures_MakeCorona();
1718
1719         // Editor light sprites
1720         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1721         "................"
1722         ".3............3."
1723         "..5...2332...5.."
1724         "...7.3....3.7..."
1725         "....7......7...."
1726         "...3.7....7.3..."
1727         "..2...7..7...2.."
1728         "..3..........3.."
1729         "..3..........3.."
1730         "..2...7..7...2.."
1731         "...3.7....7.3..."
1732         "....7......7...."
1733         "...7.3....3.7..."
1734         "..5...2332...5.."
1735         ".3............3."
1736         "................"
1737         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1738         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1739         "................"
1740         "................"
1741         "......1111......"
1742         "....11233211...."
1743         "...1234554321..."
1744         "...1356776531..."
1745         "..124677776421.."
1746         "..135777777531.."
1747         "..135777777531.."
1748         "..124677776421.."
1749         "...1356776531..."
1750         "...1234554321..."
1751         "....11233211...."
1752         "......1111......"
1753         "................"
1754         "................"
1755         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1756         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1757         "................"
1758         "................"
1759         "......1111......"
1760         "....11233211...."
1761         "...1234554321..."
1762         "...1356226531..."
1763         "..12462..26421.."
1764         "..1352....2531.."
1765         "..1352....2531.."
1766         "..12462..26421.."
1767         "...1356226531..."
1768         "...1234554321..."
1769         "....11233211...."
1770         "......1111......"
1771         "................"
1772         "................"
1773         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1774         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1775         "................"
1776         "................"
1777         "......2772......"
1778         "....27755772...."
1779         "..277533335772.."
1780         "..753333333357.."
1781         "..777533335777.."
1782         "..735775577537.."
1783         "..733357753337.."
1784         "..733337733337.."
1785         "..753337733357.."
1786         "..277537735772.."
1787         "....27777772...."
1788         "......2772......"
1789         "................"
1790         "................"
1791         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1792         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1793         "................"
1794         "................"
1795         "......2772......"
1796         "....27722772...."
1797         "..2772....2772.."
1798         "..72........27.."
1799         "..7772....2777.."
1800         "..7.27722772.7.."
1801         "..7...2772...7.."
1802         "..7....77....7.."
1803         "..72...77...27.."
1804         "..2772.77.2772.."
1805         "....27777772...."
1806         "......2772......"
1807         "................"
1808         "................"
1809         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1810         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1811         "................"
1812         ".777752..257777."
1813         ".742........247."
1814         ".72..........27."
1815         ".7............7."
1816         ".5............5."
1817         ".2............2."
1818         "................"
1819         "................"
1820         ".2............2."
1821         ".5............5."
1822         ".7............7."
1823         ".72..........27."
1824         ".742........247."
1825         ".777752..257777."
1826         "................"
1827         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1828 }
1829
1830 void R_Shadow_ValidateCvars(void)
1831 {
1832         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
1833                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
1834         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
1835                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
1836         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
1837                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
1838 }
1839
1840 void R_Shadow_RenderMode_Begin(void)
1841 {
1842 #if 0
1843         GLint drawbuffer;
1844         GLint readbuffer;
1845 #endif
1846         R_Shadow_ValidateCvars();
1847
1848         if (!r_shadow_attenuation2dtexture
1849          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
1850          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1851          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1852                 R_Shadow_MakeTextures();
1853
1854         CHECKGLERROR
1855         R_Mesh_ColorPointer(NULL, 0, 0);
1856         R_Mesh_ResetTextureState();
1857         GL_BlendFunc(GL_ONE, GL_ZERO);
1858         GL_DepthRange(0, 1);
1859         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1860         GL_DepthTest(true);
1861         GL_DepthMask(false);
1862         GL_Color(0, 0, 0, 1);
1863         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1864
1865         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1866
1867         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
1868         {
1869                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
1870                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
1871         }
1872         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
1873         {
1874                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
1875                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
1876         }
1877         else
1878         {
1879                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
1880                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
1881         }
1882
1883         switch(vid.renderpath)
1884         {
1885         case RENDERPATH_GL20:
1886                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1887                 break;
1888         case RENDERPATH_GL13:
1889         case RENDERPATH_GL11:
1890                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
1891                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
1892                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
1893                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
1894                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
1895                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
1896                 else
1897                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
1898                 break;
1899         }
1900
1901         CHECKGLERROR
1902 #if 0
1903         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1904         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1905         r_shadow_drawbuffer = drawbuffer;
1906         r_shadow_readbuffer = readbuffer;
1907 #endif
1908         r_shadow_cullface_front = r_refdef.view.cullface_front;
1909         r_shadow_cullface_back = r_refdef.view.cullface_back;
1910 }
1911
1912 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
1913 {
1914         rsurface.rtlight = rtlight;
1915 }
1916
1917 void R_Shadow_RenderMode_Reset(void)
1918 {
1919         CHECKGLERROR
1920         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE)
1921         {
1922                 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1923         }
1924         if (vid.support.ext_framebuffer_object)
1925         {
1926                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
1927         }
1928 #if 0
1929         qglDrawBuffer(r_shadow_drawbuffer);CHECKGLERROR
1930         qglReadBuffer(r_shadow_readbuffer);CHECKGLERROR
1931 #endif
1932         R_SetViewport(&r_refdef.view.viewport);
1933         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
1934         R_Mesh_ColorPointer(NULL, 0, 0);
1935         R_Mesh_ResetTextureState();
1936         GL_DepthRange(0, 1);
1937         GL_DepthTest(true);
1938         GL_DepthMask(false);
1939         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1940         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1941         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1942         qglStencilMask(~0);CHECKGLERROR
1943         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1944         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1945         r_refdef.view.cullface_front = r_shadow_cullface_front;
1946         r_refdef.view.cullface_back = r_shadow_cullface_back;
1947         GL_CullFace(r_refdef.view.cullface_back);
1948         GL_Color(1, 1, 1, 1);
1949         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
1950         GL_BlendFunc(GL_ONE, GL_ZERO);
1951         R_SetupGenericShader(false);
1952         r_shadow_usingshadowmaprect = false;
1953         r_shadow_usingshadowmapcube = false;
1954         r_shadow_usingshadowmap2d = false;
1955         CHECKGLERROR
1956 }
1957
1958 void R_Shadow_ClearStencil(void)
1959 {
1960         CHECKGLERROR
1961         GL_Clear(GL_STENCIL_BUFFER_BIT);
1962         r_refdef.stats.lights_clears++;
1963 }
1964
1965 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
1966 {
1967         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
1968         if (r_shadow_rendermode == mode)
1969                 return;
1970         CHECKGLERROR
1971         R_Shadow_RenderMode_Reset();
1972         GL_ColorMask(0, 0, 0, 0);
1973         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
1974         R_SetupDepthOrShadowShader();
1975         qglDepthFunc(GL_LESS);CHECKGLERROR
1976         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1977         r_shadow_rendermode = mode;
1978         switch(mode)
1979         {
1980         default:
1981                 break;
1982         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
1983                 GL_CullFace(GL_NONE);
1984                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
1985                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
1986                 break;
1987         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
1988                 GL_CullFace(GL_NONE);
1989                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
1990                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
1991                 break;
1992         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
1993                 GL_CullFace(GL_NONE);
1994                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1995                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
1996                 qglStencilMask(~0);CHECKGLERROR
1997                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
1998                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
1999                 qglStencilMask(~0);CHECKGLERROR
2000                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
2001                 break;
2002         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2003                 GL_CullFace(GL_NONE);
2004                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2005                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
2006                 qglStencilMask(~0);CHECKGLERROR
2007                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
2008                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
2009                 qglStencilMask(~0);CHECKGLERROR
2010                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
2011                 break;
2012         }
2013 }
2014
2015 static void R_Shadow_MakeVSDCT(void)
2016 {
2017         // maps to a 2x3 texture rectangle with normalized coordinates
2018         // +-
2019         // XX
2020         // YY
2021         // ZZ
2022         // stores abs(dir.xy), offset.xy/2.5
2023         unsigned char data[4*6] =
2024         {
2025                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2026                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2027                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2028                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2029                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2030                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2031         };
2032         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, NULL); 
2033 }
2034
2035 void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
2036 {
2037         int status;
2038         int maxsize;
2039         float nearclip, farclip, bias;
2040         r_viewport_t viewport;
2041         GLuint fbo = 0;
2042         CHECKGLERROR
2043         maxsize = r_shadow_shadowmapmaxsize;
2044         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2045         farclip = 1.0f;
2046         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2047         r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2048         r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2049         r_shadow_shadowmapside = side;
2050         r_shadow_shadowmapsize = size;
2051         if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2052         {
2053                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2054                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2055                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2056                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
2057
2058                 // complex unrolled cube approach (more flexible)
2059                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2060                         R_Shadow_MakeVSDCT();
2061                 if (!r_shadow_shadowmap2dtexture)
2062                 {
2063 #if 1
2064                         int w = maxsize*2, h = vid.support.arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
2065                         r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2066                         qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
2067                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
2068                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
2069             // render depth into the fbo, do not render color at all
2070                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2071                         qglReadBuffer(GL_NONE);CHECKGLERROR
2072                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2073                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
2074                         {
2075                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2076                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2077                         }
2078 #endif
2079                 }
2080                 CHECKGLERROR
2081                 if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
2082                 r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
2083                 r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
2084                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2085         }
2086         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2087         {
2088                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2089                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2090                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2091                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
2092
2093                 // complex unrolled cube approach (more flexible)
2094                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2095                         R_Shadow_MakeVSDCT();
2096                 if (!r_shadow_shadowmaprectangletexture)
2097                 {
2098 #if 1
2099                         r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2100                         qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
2101                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
2102                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
2103                         // render depth into the fbo, do not render color at all
2104                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2105                         qglReadBuffer(GL_NONE);CHECKGLERROR
2106                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2107                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
2108                         {
2109                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2110                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2111                         }
2112 #endif
2113                 }
2114                 CHECKGLERROR
2115                 if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
2116                 r_shadow_shadowmap_texturescale[0] = 1.0f;
2117                 r_shadow_shadowmap_texturescale[1] = 1.0f;
2118                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
2119         }
2120         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2121         {
2122                 r_shadow_shadowmap_parameters[0] = 1.0f;
2123                 r_shadow_shadowmap_parameters[1] = 1.0f;
2124                 R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
2125                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
2126
2127                 // simple cube approach
2128                 if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
2129                 {
2130  #if 1
2131                         r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2132                         qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2133                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2134                         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
2135                         // render depth into the fbo, do not render color at all
2136                         qglDrawBuffer(GL_NONE);CHECKGLERROR
2137                         qglReadBuffer(GL_NONE);CHECKGLERROR
2138                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2139                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
2140                         {
2141                                 Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2142                                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2143                         }
2144  #endif
2145                 }
2146                 CHECKGLERROR
2147                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
2148                 r_shadow_shadowmap_texturescale[0] = 0.0f;
2149                 r_shadow_shadowmap_texturescale[1] = 0.0f;
2150                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
2151         }
2152
2153         R_Shadow_RenderMode_Reset();
2154         if (fbo)
2155         {
2156                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
2157                 R_SetupDepthOrShadowShader();
2158         }
2159         else
2160         {
2161                 R_SetupShowDepthShader();
2162                 qglClearColor(1,1,1,1);CHECKGLERROR
2163         }
2164         CHECKGLERROR
2165         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2166         GL_DepthMask(true);
2167         GL_DepthTest(true);
2168         qglClearDepth(1);
2169         CHECKGLERROR
2170
2171 init_done:
2172         R_SetViewport(&viewport);
2173         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2174         if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE)
2175         {
2176                 int flipped = (side&1)^(side>>2);
2177                 r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2178                 r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2179                 GL_CullFace(r_refdef.view.cullface_back);
2180         }
2181         else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE)
2182         {
2183                 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
2184         }
2185         if (clear)
2186                 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |  GL_STENCIL_BUFFER_BIT);
2187         CHECKGLERROR
2188 }
2189
2190 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
2191 {
2192         if (transparent)
2193         {
2194                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2195                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2196                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2197                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2198         }
2199         CHECKGLERROR
2200         R_Shadow_RenderMode_Reset();
2201         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2202         if (!transparent)
2203         {
2204                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2205         }
2206         if (stenciltest)
2207         {
2208                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2209                 // only draw light where this geometry was already rendered AND the
2210                 // stencil is 128 (values other than this mean shadow)
2211                 qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
2212         }
2213         r_shadow_rendermode = r_shadow_lightingrendermode;
2214         // do global setup needed for the chosen lighting mode
2215         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2216         {
2217                 R_Mesh_TexBindAll(GL20TU_CUBE, 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap), 0); // light filter
2218                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2219                 CHECKGLERROR
2220                 if (shadowmapping)
2221                 {
2222                         if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2223                         {
2224                                 r_shadow_usingshadowmap2d = true;
2225                                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
2226                                 CHECKGLERROR
2227                         }
2228                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2229                         {
2230                                 r_shadow_usingshadowmaprect = true;
2231                                 R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT, 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture));
2232                                 CHECKGLERROR
2233                         }
2234                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2235                         {
2236                                 r_shadow_usingshadowmapcube = true;
2237                                 R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE, 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
2238                                 CHECKGLERROR
2239                         }
2240
2241                         if (r_shadow_shadowmapvsdct && (r_shadow_usingshadowmap2d || r_shadow_usingshadowmaprect))
2242                         {
2243                                 R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION, 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture), 0);
2244                                 CHECKGLERROR
2245                         }
2246                 }
2247         }
2248         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
2249         //GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2250         CHECKGLERROR
2251 }
2252
2253 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
2254 {
2255         CHECKGLERROR
2256         R_Shadow_RenderMode_Reset();
2257         GL_BlendFunc(GL_ONE, GL_ONE);
2258         GL_DepthRange(0, 1);
2259         GL_DepthTest(r_showshadowvolumes.integer < 2);
2260         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
2261         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2262         GL_CullFace(GL_NONE);
2263         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
2264 }
2265
2266 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
2267 {
2268         CHECKGLERROR
2269         R_Shadow_RenderMode_Reset();
2270         GL_BlendFunc(GL_ONE, GL_ONE);
2271         GL_DepthRange(0, 1);
2272         GL_DepthTest(r_showlighting.integer < 2);
2273         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2274         if (!transparent)
2275         {
2276                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2277         }
2278         if (stenciltest)
2279         {
2280                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2281                 qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
2282         }
2283         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2284 }
2285
2286 void R_Shadow_RenderMode_End(void)
2287 {
2288         CHECKGLERROR
2289         R_Shadow_RenderMode_Reset();
2290         R_Shadow_RenderMode_ActiveLight(NULL);
2291         GL_DepthMask(true);
2292         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2293         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2294 }
2295
2296 int bboxedges[12][2] =
2297 {
2298         // top
2299         {0, 1}, // +X
2300         {0, 2}, // +Y
2301         {1, 3}, // Y, +X
2302         {2, 3}, // X, +Y
2303         // bottom
2304         {4, 5}, // +X
2305         {4, 6}, // +Y
2306         {5, 7}, // Y, +X
2307         {6, 7}, // X, +Y
2308         // verticals
2309         {0, 4}, // +Z
2310         {1, 5}, // X, +Z
2311         {2, 6}, // Y, +Z
2312         {3, 7}, // XY, +Z
2313 };
2314
2315 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2316 {
2317         int i, ix1, iy1, ix2, iy2;
2318         float x1, y1, x2, y2;
2319         vec4_t v, v2;
2320         float vertex[20][3];
2321         int j, k;
2322         vec4_t plane4f;
2323         int numvertices;
2324         float corner[8][4];
2325         float dist[8];
2326         int sign[8];
2327         float f;
2328
2329         r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2330         r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2331         r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2332         r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2333
2334         if (!r_shadow_scissor.integer)
2335                 return false;
2336
2337         // if view is inside the light box, just say yes it's visible
2338         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
2339                 return false;
2340
2341         x1 = y1 = x2 = y2 = 0;
2342
2343         // transform all corners that are infront of the nearclip plane
2344         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
2345         plane4f[3] = r_refdef.view.frustum[4].dist;
2346         numvertices = 0;
2347         for (i = 0;i < 8;i++)
2348         {
2349                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
2350                 dist[i] = DotProduct4(corner[i], plane4f);
2351                 sign[i] = dist[i] > 0;
2352                 if (!sign[i])
2353                 {
2354                         VectorCopy(corner[i], vertex[numvertices]);
2355                         numvertices++;
2356                 }
2357         }
2358         // if some points are behind the nearclip, add clipped edge points to make
2359         // sure that the scissor boundary is complete
2360         if (numvertices > 0 && numvertices < 8)
2361         {
2362                 // add clipped edge points
2363                 for (i = 0;i < 12;i++)
2364                 {
2365                         j = bboxedges[i][0];
2366                         k = bboxedges[i][1];
2367                         if (sign[j] != sign[k])
2368                         {
2369                                 f = dist[j] / (dist[j] - dist[k]);
2370                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
2371                                 numvertices++;
2372                         }
2373                 }
2374         }
2375
2376         // if we have no points to check, the light is behind the view plane
2377         if (!numvertices)
2378                 return true;
2379
2380         // if we have some points to transform, check what screen area is covered
2381         x1 = y1 = x2 = y2 = 0;
2382         v[3] = 1.0f;
2383         //Con_Printf("%i vertices to transform...\n", numvertices);
2384         for (i = 0;i < numvertices;i++)
2385         {
2386                 VectorCopy(vertex[i], v);
2387                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
2388                 //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]);
2389                 if (i)
2390                 {
2391                         if (x1 > v2[0]) x1 = v2[0];
2392                         if (x2 < v2[0]) x2 = v2[0];
2393                         if (y1 > v2[1]) y1 = v2[1];
2394                         if (y2 < v2[1]) y2 = v2[1];
2395                 }
2396                 else
2397                 {
2398                         x1 = x2 = v2[0];
2399                         y1 = y2 = v2[1];
2400                 }
2401         }
2402
2403         // now convert the scissor rectangle to integer screen coordinates
2404         ix1 = (int)(x1 - 1.0f);
2405         iy1 = vid.height - (int)(y2 - 1.0f);
2406         ix2 = (int)(x2 + 1.0f);
2407         iy2 = vid.height - (int)(y1 + 1.0f);
2408         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
2409
2410         // clamp it to the screen
2411         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
2412         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
2413         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
2414         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
2415
2416         // if it is inside out, it's not visible
2417         if (ix2 <= ix1 || iy2 <= iy1)
2418                 return true;
2419
2420         // the light area is visible, set up the scissor rectangle
2421         r_shadow_lightscissor[0] = ix1;
2422         r_shadow_lightscissor[1] = iy1;
2423         r_shadow_lightscissor[2] = ix2 - ix1;
2424         r_shadow_lightscissor[3] = iy2 - iy1;
2425
2426         r_refdef.stats.lights_scissored++;
2427         return false;
2428 }
2429
2430 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
2431 {
2432         const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
2433         const float *normal3f = rsurface.normal3f + 3 * firstvertex;
2434         float *color4f = rsurface.array_color4f + 4 * firstvertex;
2435         float dist, dot, distintensity, shadeintensity, v[3], n[3];
2436         switch (r_shadow_rendermode)
2437         {
2438         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2439         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2440                 if (VectorLength2(diffusecolor) > 0)
2441                 {
2442                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2443                         {
2444                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2445                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2446                                 if ((dot = DotProduct(n, v)) < 0)
2447                                 {
2448                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2449                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
2450                                 }
2451                                 else
2452                                         VectorCopy(ambientcolor, color4f);
2453                                 if (r_refdef.fogenabled)
2454                                 {
2455                                         float f;
2456                                         f = RSurf_FogVertex(vertex3f);
2457                                         VectorScale(color4f, f, color4f);
2458                                 }
2459                                 color4f[3] = 1;
2460                         }
2461                 }
2462                 else
2463                 {
2464                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2465                         {
2466                                 VectorCopy(ambientcolor, color4f);
2467                                 if (r_refdef.fogenabled)
2468                                 {
2469                                         float f;
2470                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2471                                         f = RSurf_FogVertex(vertex3f);
2472                                         VectorScale(color4f, f, color4f);
2473                                 }
2474                                 color4f[3] = 1;
2475                         }
2476                 }
2477                 break;
2478         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2479                 if (VectorLength2(diffusecolor) > 0)
2480                 {
2481                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2482                         {
2483                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2484                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2485                                 {
2486                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2487                                         if ((dot = DotProduct(n, v)) < 0)
2488                                         {
2489                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2490                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2491                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2492                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2493                                         }
2494                                         else
2495                                         {
2496                                                 color4f[0] = ambientcolor[0] * distintensity;
2497                                                 color4f[1] = ambientcolor[1] * distintensity;
2498                                                 color4f[2] = ambientcolor[2] * distintensity;
2499                                         }
2500                                         if (r_refdef.fogenabled)
2501                                         {
2502                                                 float f;
2503                                                 f = RSurf_FogVertex(vertex3f);
2504                                                 VectorScale(color4f, f, color4f);
2505                                         }
2506                                 }
2507                                 else
2508                                         VectorClear(color4f);
2509                                 color4f[3] = 1;
2510                         }
2511                 }
2512                 else
2513                 {
2514                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2515                         {
2516                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2517                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2518                                 {
2519                                         color4f[0] = ambientcolor[0] * distintensity;
2520                                         color4f[1] = ambientcolor[1] * distintensity;
2521                                         color4f[2] = ambientcolor[2] * distintensity;
2522                                         if (r_refdef.fogenabled)
2523                                         {
2524                                                 float f;
2525                                                 f = RSurf_FogVertex(vertex3f);
2526                                                 VectorScale(color4f, f, color4f);
2527                                         }
2528                                 }
2529                                 else
2530                                         VectorClear(color4f);
2531                                 color4f[3] = 1;
2532                         }
2533                 }
2534                 break;
2535         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2536                 if (VectorLength2(diffusecolor) > 0)
2537                 {
2538                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2539                         {
2540                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2541                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2542                                 {
2543                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2544                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2545                                         if ((dot = DotProduct(n, v)) < 0)
2546                                         {
2547                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2548                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2549                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2550                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2551                                         }
2552                                         else
2553                                         {
2554                                                 color4f[0] = ambientcolor[0] * distintensity;
2555                                                 color4f[1] = ambientcolor[1] * distintensity;
2556                                                 color4f[2] = ambientcolor[2] * distintensity;
2557                                         }
2558                                         if (r_refdef.fogenabled)
2559                                         {
2560                                                 float f;
2561                                                 f = RSurf_FogVertex(vertex3f);
2562                                                 VectorScale(color4f, f, color4f);
2563                                         }
2564                                 }
2565                                 else
2566                                         VectorClear(color4f);
2567                                 color4f[3] = 1;
2568                         }
2569                 }
2570                 else
2571                 {
2572                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2573                         {
2574                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2575                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2576                                 {
2577                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2578                                         color4f[0] = ambientcolor[0] * distintensity;
2579                                         color4f[1] = ambientcolor[1] * distintensity;
2580                                         color4f[2] = ambientcolor[2] * distintensity;
2581                                         if (r_refdef.fogenabled)
2582                                         {
2583                                                 float f;
2584                                                 f = RSurf_FogVertex(vertex3f);
2585                                                 VectorScale(color4f, f, color4f);
2586                                         }
2587                                 }
2588                                 else
2589                                         VectorClear(color4f);
2590                                 color4f[3] = 1;
2591                         }
2592                 }
2593                 break;
2594         default:
2595                 break;
2596         }
2597 }
2598
2599 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)
2600 {
2601         // used to display how many times a surface is lit for level design purposes
2602         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2603 }
2604
2605 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)
2606 {
2607         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2608         R_SetupSurfaceShader(lightcolorbase, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT);
2609         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
2610                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
2611         else
2612                 R_Mesh_ColorPointer(NULL, 0, 0);
2613         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
2614         R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
2615         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
2616         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
2617         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
2618         if (rsurface.texture->backgroundcurrentskinframe)
2619         {
2620                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
2621                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
2622                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
2623                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
2624         }
2625         //R_Mesh_TexBindAll(GL20TU_CUBE, 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap), 0);
2626         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
2627         if(rsurface.texture->colormapping)
2628         {
2629                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
2630                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
2631         }
2632         R_Mesh_TexBind(GL20TU_ATTENUATION, R_GetTexture(r_shadow_attenuationgradienttexture));
2633         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
2634         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
2635         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
2636         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
2637         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2638         {
2639                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2640         }
2641         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2642         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2643         {
2644                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2645         }
2646 }
2647
2648 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
2649 {
2650         int renders;
2651         int i;
2652         int stop;
2653         int newfirstvertex;
2654         int newlastvertex;
2655         int newnumtriangles;
2656         int *newe;
2657         const int *e;
2658         float *c;
2659         int maxtriangles = 4096;
2660         int newelements[4096*3];
2661         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2);
2662         for (renders = 0;renders < 64;renders++)
2663         {
2664                 stop = true;
2665                 newfirstvertex = 0;
2666                 newlastvertex = 0;
2667                 newnumtriangles = 0;
2668                 newe = newelements;
2669                 // due to low fillrate on the cards this vertex lighting path is
2670                 // designed for, we manually cull all triangles that do not
2671                 // contain a lit vertex
2672                 // this builds batches of triangles from multiple surfaces and
2673                 // renders them at once
2674                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
2675                 {
2676                         if (VectorLength2(rsurface.array_color4f + e[0] * 4) + VectorLength2(rsurface.array_color4f + e[1] * 4) + VectorLength2(rsurface.array_color4f + e[2] * 4) >= 0.01)
2677                         {
2678                                 if (newnumtriangles)
2679                                 {
2680                                         newfirstvertex = min(newfirstvertex, e[0]);
2681                                         newlastvertex  = max(newlastvertex, e[0]);
2682                                 }
2683                                 else
2684                                 {
2685                                         newfirstvertex = e[0];
2686                                         newlastvertex = e[0];
2687                                 }
2688                                 newfirstvertex = min(newfirstvertex, e[1]);
2689                                 newlastvertex  = max(newlastvertex, e[1]);
2690                                 newfirstvertex = min(newfirstvertex, e[2]);
2691                                 newlastvertex  = max(newlastvertex, e[2]);
2692                                 newe[0] = e[0];
2693                                 newe[1] = e[1];
2694                                 newe[2] = e[2];
2695                                 newnumtriangles++;
2696                                 newe += 3;
2697                                 if (newnumtriangles >= maxtriangles)
2698                                 {
2699                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2700                                         newnumtriangles = 0;
2701                                         newe = newelements;
2702                                         stop = false;
2703                                 }
2704                         }
2705                 }
2706                 if (newnumtriangles >= 1)
2707                 {
2708                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2709                         stop = false;
2710                 }
2711                 // if we couldn't find any lit triangles, exit early
2712                 if (stop)
2713                         break;
2714                 // now reduce the intensity for the next overbright pass
2715                 // we have to clamp to 0 here incase the drivers have improper
2716                 // handling of negative colors
2717                 // (some old drivers even have improper handling of >1 color)
2718                 stop = true;
2719                 for (i = 0, c = rsurface.array_color4f + 4 * firstvertex;i < numvertices;i++, c += 4)
2720                 {
2721                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
2722                         {
2723                                 c[0] = max(0, c[0] - 1);
2724                                 c[1] = max(0, c[1] - 1);
2725                                 c[2] = max(0, c[2] - 1);
2726                                 stop = false;
2727                         }
2728                         else
2729                                 VectorClear(c);
2730                 }
2731                 // another check...
2732                 if (stop)
2733                         break;
2734         }
2735 }
2736
2737 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)
2738 {
2739         // OpenGL 1.1 path (anything)
2740         float ambientcolorbase[3], diffusecolorbase[3];
2741         float ambientcolorpants[3], diffusecolorpants[3];
2742         float ambientcolorshirt[3], diffusecolorshirt[3];
2743         rmeshstate_t m;
2744         VectorScale(lightcolorbase, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorbase);
2745         VectorScale(lightcolorbase, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorbase);
2746         VectorScale(lightcolorpants, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorpants);
2747         VectorScale(lightcolorpants, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorpants);
2748         VectorScale(lightcolorshirt, ambientscale * 2 * r_refdef.view.colorscale, ambientcolorshirt);
2749         VectorScale(lightcolorshirt, diffusescale * 2 * r_refdef.view.colorscale, diffusecolorshirt);
2750         switch(r_shadow_rendermode)
2751         {
2752         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2753                 memset(&m, 0, sizeof(m));
2754                 m.tex[0] = R_GetTexture(basetexture);
2755                 m.texmatrix[0] = rsurface.texture->currenttexmatrix;
2756                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
2757                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
2758                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
2759                 m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
2760                 m.texmatrix[1] = rsurface.entitytoattenuationxyz;
2761                 m.pointer_texcoord3f[1] = rsurface.vertex3f;
2762                 m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
2763                 m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
2764                 R_Mesh_TextureState(&m);
2765                 break;
2766         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2767                 memset(&m, 0, sizeof(m));
2768                 m.tex[0] = R_GetTexture(basetexture);
2769                 m.texmatrix[0] = rsurface.texture->currenttexmatrix;
2770                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
2771                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
2772                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
2773                 m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
2774                 m.texmatrix[1] = rsurface.entitytoattenuationxyz;
2775                 m.pointer_texcoord3f[1] = rsurface.vertex3f;
2776                 m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
2777                 m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
2778                 m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
2779                 m.texmatrix[2] = rsurface.entitytoattenuationz;
2780                 m.pointer_texcoord3f[2] = rsurface.vertex3f;
2781                 m.pointer_texcoord_bufferobject[2] = rsurface.vertex3f_bufferobject;
2782                 m.pointer_texcoord_bufferoffset[2] = rsurface.vertex3f_bufferoffset;
2783                 R_Mesh_TextureState(&m);
2784                 break;
2785         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2786                 memset(&m, 0, sizeof(m));
2787                 m.tex[0] = R_GetTexture(basetexture);
2788                 m.texmatrix[0] = rsurface.texture->currenttexmatrix;
2789                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
2790                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
2791                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
2792                 m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
2793                 m.texmatrix[1] = rsurface.entitytoattenuationxyz;
2794                 m.pointer_texcoord3f[1] = rsurface.vertex3f;
2795                 m.pointer_texcoord_bufferobject[1] = rsurface.vertex3f_bufferobject;
2796                 m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
2797                 R_Mesh_TextureState(&m);
2798                 break;
2799         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2800                 memset(&m, 0, sizeof(m));
2801                 m.tex[0] = R_GetTexture(basetexture);
2802                 m.texmatrix[0] = rsurface.texture->currenttexmatrix;
2803                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
2804                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
2805                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
2806                 R_Mesh_TextureState(&m);
2807                 break;
2808         default:
2809                 break;
2810         }
2811         //R_Mesh_TexBind(0, R_GetTexture(basetexture));
2812         R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase);
2813         if (dopants)
2814         {
2815                 R_Mesh_TexBind(0, R_GetTexture(pantstexture));
2816                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants);
2817         }
2818         if (doshirt)
2819         {
2820                 R_Mesh_TexBind(0, R_GetTexture(shirttexture));
2821                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt);
2822         }
2823 }
2824
2825 extern cvar_t gl_lightmaps;
2826 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)
2827 {
2828         float ambientscale, diffusescale, specularscale;
2829         qboolean negated;
2830         vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
2831         rtexture_t *nmap;
2832         // calculate colors to render this texture with
2833         lightcolorbase[0] = rsurface.rtlight->currentcolor[0] * rsurface.texture->dlightcolor[0];
2834         lightcolorbase[1] = rsurface.rtlight->currentcolor[1] * rsurface.texture->dlightcolor[1];
2835         lightcolorbase[2] = rsurface.rtlight->currentcolor[2] * rsurface.texture->dlightcolor[2];
2836         ambientscale = rsurface.rtlight->ambientscale;
2837         diffusescale = rsurface.rtlight->diffusescale;
2838         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
2839         if (!r_shadow_usenormalmap.integer)
2840         {
2841                 ambientscale += 1.0f * diffusescale;
2842                 diffusescale = 0;
2843                 specularscale = 0;
2844         }
2845         if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
2846                 return;
2847         negated = (lightcolorbase[0] + lightcolorbase[1] + lightcolorbase[2] < 0) && vid.support.ext_blend_subtract;
2848         if(negated)
2849         {
2850                 VectorNegate(lightcolorbase, lightcolorbase);
2851                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2852         }
2853         RSurf_SetupDepthAndCulling();
2854         nmap = rsurface.texture->currentskinframe->nmap;
2855         if (gl_lightmaps.integer)
2856                 nmap = r_texture_blanknormalmap;
2857         if (rsurface.texture->colormapping && !gl_lightmaps.integer)
2858         {
2859                 qboolean dopants = rsurface.texture->currentskinframe->pants != NULL && VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f);
2860                 qboolean doshirt = rsurface.texture->currentskinframe->shirt != NULL && VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
2861                 if (dopants)
2862                 {
2863                         lightcolorpants[0] = lightcolorbase[0] * rsurface.colormap_pantscolor[0];
2864                         lightcolorpants[1] = lightcolorbase[1] * rsurface.colormap_pantscolor[1];
2865                         lightcolorpants[2] = lightcolorbase[2] * rsurface.colormap_pantscolor[2];
2866                 }
2867                 else
2868                         VectorClear(lightcolorpants);
2869                 if (doshirt)
2870                 {
2871                         lightcolorshirt[0] = lightcolorbase[0] * rsurface.colormap_shirtcolor[0];
2872                         lightcolorshirt[1] = lightcolorbase[1] * rsurface.colormap_shirtcolor[1];
2873                         lightcolorshirt[2] = lightcolorbase[2] * rsurface.colormap_shirtcolor[2];
2874                 }
2875                 else
2876                         VectorClear(lightcolorshirt);
2877                 switch (r_shadow_rendermode)
2878                 {
2879                 case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
2880                         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
2881                         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);
2882                         break;
2883                 case R_SHADOW_RENDERMODE_LIGHT_GLSL:
2884                         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);
2885                         break;
2886                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2887                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2888                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2889                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2890                         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);
2891                         break;
2892                 default:
2893                         Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2894                         break;
2895                 }
2896         }
2897         else
2898         {
2899                 switch (r_shadow_rendermode)
2900                 {
2901                 case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
2902                         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
2903                         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);
2904                         break;
2905                 case R_SHADOW_RENDERMODE_LIGHT_GLSL:
2906                         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);
2907                         break;
2908                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2909                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2910                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2911                 case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2912                         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);
2913                         break;
2914                 default:
2915                         Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2916                         break;
2917                 }
2918         }
2919         if(negated)
2920                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2921 }
2922
2923 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)
2924 {
2925         matrix4x4_t tempmatrix = *matrix;
2926         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
2927
2928         // if this light has been compiled before, free the associated data
2929         R_RTLight_Uncompile(rtlight);
2930
2931         // clear it completely to avoid any lingering data
2932         memset(rtlight, 0, sizeof(*rtlight));
2933
2934         // copy the properties
2935         rtlight->matrix_lighttoworld = tempmatrix;
2936         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
2937         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
2938         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
2939         VectorCopy(color, rtlight->color);
2940         rtlight->cubemapname[0] = 0;
2941         if (cubemapname && cubemapname[0])
2942                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
2943         rtlight->shadow = shadow;
2944         rtlight->corona = corona;
2945         rtlight->style = style;
2946         rtlight->isstatic = isstatic;
2947         rtlight->coronasizescale = coronasizescale;
2948         rtlight->ambientscale = ambientscale;
2949         rtlight->diffusescale = diffusescale;
2950         rtlight->specularscale = specularscale;
2951         rtlight->flags = flags;
2952
2953         // compute derived data
2954         //rtlight->cullradius = rtlight->radius;
2955         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
2956         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2957         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2958         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2959         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2960         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2961         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2962 }
2963
2964 // compiles rtlight geometry
2965 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
2966 void R_RTLight_Compile(rtlight_t *rtlight)
2967 {
2968         int i;
2969         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
2970         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
2971         entity_render_t *ent = r_refdef.scene.worldentity;
2972         dp_model_t *model = r_refdef.scene.worldmodel;
2973         unsigned char *data;
2974         shadowmesh_t *mesh;
2975
2976         // compile the light
2977         rtlight->compiled = true;
2978         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
2979         rtlight->static_numleafs = 0;
2980         rtlight->static_numleafpvsbytes = 0;
2981         rtlight->static_leaflist = NULL;
2982         rtlight->static_leafpvs = NULL;
2983         rtlight->static_numsurfaces = 0;
2984         rtlight->static_surfacelist = NULL;
2985         rtlight->static_shadowmap_receivers = 0x3F;
2986         rtlight->static_shadowmap_casters = 0x3F;
2987         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2988         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2989         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2990         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2991         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2992         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2993
2994         if (model && model->GetLightInfo)
2995         {
2996                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
2997                 r_shadow_compilingrtlight = rtlight;
2998                 model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs, 0, NULL);
2999                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
3000                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
3001                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
3002                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
3003                 rtlight->static_numsurfaces = numsurfaces;
3004                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
3005                 rtlight->static_numleafs = numleafs;
3006                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
3007                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
3008                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
3009                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
3010                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
3011                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
3012                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
3013                 if (rtlight->static_numsurfaces)
3014                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
3015                 if (rtlight->static_numleafs)
3016                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3017                 if (rtlight->static_numleafpvsbytes)
3018                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
3019                 if (rtlight->static_numshadowtrispvsbytes)
3020                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
3021                 if (rtlight->static_numlighttrispvsbytes)
3022                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
3023                 switch (rtlight->shadowmode)
3024                 {
3025                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
3026                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
3027                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
3028                         if (model->CompileShadowMap && rtlight->shadow)
3029                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3030                         break;
3031                 default:
3032                         if (model->CompileShadowVolume && rtlight->shadow)
3033                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3034                         break;
3035                 }
3036                 // now we're done compiling the rtlight
3037                 r_shadow_compilingrtlight = NULL;
3038         }
3039
3040
3041         // use smallest available cullradius - box radius or light radius
3042         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
3043         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
3044
3045         shadowzpasstris = 0;
3046         if (rtlight->static_meshchain_shadow_zpass)
3047                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
3048                         shadowzpasstris += mesh->numtriangles;
3049
3050         shadowzfailtris = 0;
3051         if (rtlight->static_meshchain_shadow_zfail)
3052                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
3053                         shadowzfailtris += mesh->numtriangles;
3054
3055         lighttris = 0;
3056         if (rtlight->static_numlighttrispvsbytes)
3057                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
3058                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
3059                                 lighttris++;
3060
3061         shadowtris = 0;
3062         if (rtlight->static_numlighttrispvsbytes)
3063                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
3064                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
3065                                 shadowtris++;
3066
3067         if (developer.integer >= 10)
3068                 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);
3069 }
3070
3071 void R_RTLight_Uncompile(rtlight_t *rtlight)
3072 {
3073         if (rtlight->compiled)
3074         {
3075                 if (rtlight->static_meshchain_shadow_zpass)
3076                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
3077                 rtlight->static_meshchain_shadow_zpass = NULL;
3078                 if (rtlight->static_meshchain_shadow_zfail)
3079                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
3080                 rtlight->static_meshchain_shadow_zfail = NULL;
3081                 if (rtlight->static_meshchain_shadow_shadowmap)
3082                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
3083                 rtlight->static_meshchain_shadow_shadowmap = NULL;
3084                 // these allocations are grouped
3085                 if (rtlight->static_surfacelist)
3086                         Mem_Free(rtlight->static_surfacelist);
3087                 rtlight->static_numleafs = 0;
3088                 rtlight->static_numleafpvsbytes = 0;
3089                 rtlight->static_leaflist = NULL;
3090                 rtlight->static_leafpvs = NULL;
3091                 rtlight->static_numsurfaces = 0;
3092                 rtlight->static_surfacelist = NULL;
3093                 rtlight->static_numshadowtrispvsbytes = 0;
3094                 rtlight->static_shadowtrispvs = NULL;
3095                 rtlight->static_numlighttrispvsbytes = 0;
3096                 rtlight->static_lighttrispvs = NULL;
3097                 rtlight->compiled = false;
3098         }
3099 }
3100
3101 void R_Shadow_UncompileWorldLights(void)
3102 {
3103         size_t lightindex;
3104         dlight_t *light;
3105         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3106         for (lightindex = 0;lightindex < range;lightindex++)
3107         {
3108                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3109                 if (!light)
3110                         continue;
3111                 R_RTLight_Uncompile(&light->rtlight);
3112         }
3113 }
3114
3115 void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
3116 {
3117         int i, j;
3118         mplane_t plane;
3119         // reset the count of frustum planes
3120         // see rtlight->cached_frustumplanes definition for how much this array
3121         // can hold
3122         rtlight->cached_numfrustumplanes = 0;
3123
3124         // haven't implemented a culling path for ortho rendering
3125         if (!r_refdef.view.useperspective)
3126         {
3127                 // check if the light is on screen and copy the 4 planes if it is
3128                 for (i = 0;i < 4;i++)
3129                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3130                                 break;
3131                 if (i == 4)
3132                         for (i = 0;i < 4;i++)
3133                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3134                 return;
3135         }
3136
3137 #if 1
3138         // generate a deformed frustum that includes the light origin, this is
3139         // used to cull shadow casting surfaces that can not possibly cast a
3140         // shadow onto the visible light-receiving surfaces, which can be a
3141         // performance gain
3142         //
3143         // if the light origin is onscreen the result will be 4 planes exactly
3144         // if the light origin is offscreen on only one axis the result will
3145         // be exactly 5 planes (split-side case)
3146         // if the light origin is offscreen on two axes the result will be
3147         // exactly 4 planes (stretched corner case)
3148         for (i = 0;i < 4;i++)
3149         {
3150                 // quickly reject standard frustum planes that put the light
3151                 // origin outside the frustum
3152                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3153                         continue;
3154                 // copy the plane
3155                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3156         }
3157         // if all the standard frustum planes were accepted, the light is onscreen
3158         // otherwise we need to generate some more planes below...
3159         if (rtlight->cached_numfrustumplanes < 4)
3160         {
3161                 // at least one of the stock frustum planes failed, so we need to
3162                 // create one or two custom planes to enclose the light origin
3163                 for (i = 0;i < 4;i++)
3164                 {
3165                         // create a plane using the view origin and light origin, and a
3166                         // single point from the frustum corner set
3167                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
3168                         VectorNormalize(plane.normal);
3169                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
3170                         // see if this plane is backwards and flip it if so
3171                         for (j = 0;j < 4;j++)
3172                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3173                                         break;
3174                         if (j < 4)
3175                         {
3176                                 VectorNegate(plane.normal, plane.normal);
3177                                 plane.dist *= -1;
3178                                 // flipped plane, test again to see if it is now valid
3179                                 for (j = 0;j < 4;j++)
3180                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3181                                                 break;
3182                                 // if the plane is still not valid, then it is dividing the
3183                                 // frustum and has to be rejected
3184                                 if (j < 4)
3185                                         continue;
3186                         }
3187                         // we have created a valid plane, compute extra info
3188                         PlaneClassify(&plane);
3189                         // copy the plane
3190                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3191 #if 1
3192                         // if we've found 5 frustum planes then we have constructed a
3193                         // proper split-side case and do not need to keep searching for
3194                         // planes to enclose the light origin
3195                         if (rtlight->cached_numfrustumplanes == 5)
3196                                 break;
3197 #endif
3198                 }
3199         }
3200 #endif
3201
3202 #if 0
3203         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
3204         {
3205                 plane = rtlight->cached_frustumplanes[i];
3206                 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));
3207         }
3208 #endif
3209
3210 #if 0
3211         // now add the light-space box planes if the light box is rotated, as any
3212         // caster outside the oriented light box is irrelevant (even if it passed
3213         // the worldspace light box, which is axial)
3214         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
3215         {
3216                 for (i = 0;i < 6;i++)
3217                 {
3218                         vec3_t v;
3219                         VectorClear(v);
3220                         v[i >> 1] = (i & 1) ? -1 : 1;
3221                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
3222                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
3223                         plane.dist = VectorNormalizeLength(plane.normal);
3224                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
3225                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3226                 }
3227         }
3228 #endif
3229
3230 #if 0
3231         // add the world-space reduced box planes
3232         for (i = 0;i < 6;i++)
3233         {
3234                 VectorClear(plane.normal);
3235                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
3236                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
3237                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3238         }
3239 #endif
3240
3241 #if 0
3242         {
3243         int j, oldnum;
3244         vec3_t points[8];
3245         vec_t bestdist;
3246         // reduce all plane distances to tightly fit the rtlight cull box, which
3247         // is in worldspace
3248         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3249         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3250         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3251         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3252         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3253         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3254         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3255         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3256         oldnum = rtlight->cached_numfrustumplanes;
3257         rtlight->cached_numfrustumplanes = 0;
3258         for (j = 0;j < oldnum;j++)
3259         {
3260                 // find the nearest point on the box to this plane
3261                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
3262                 for (i = 1;i < 8;i++)
3263                 {
3264                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
3265                         if (bestdist > dist)
3266                                 bestdist = dist;
3267                 }
3268                 Con_Printf("light %p %splane #%i %f %f %f : %f < %f\n", rtlight, rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125 ? "^2" : "^1", j, rtlight->cached_frustumplanes[j].normal[0], rtlight->cached_frustumplanes[j].normal[1], rtlight->cached_frustumplanes[j].normal[2], rtlight->cached_frustumplanes[j].dist, bestdist);
3269                 // if the nearest point is near or behind the plane, we want this
3270                 // plane, otherwise the plane is useless as it won't cull anything
3271                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
3272                 {
3273                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
3274                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
3275                 }
3276         }
3277         }
3278 #endif
3279 }
3280
3281 void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
3282 {
3283         shadowmesh_t *mesh;
3284
3285         RSurf_ActiveWorldEntity();
3286
3287         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3288         {
3289                 CHECKGLERROR
3290                 GL_CullFace(GL_NONE);
3291         mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
3292         for (;mesh;mesh = mesh->next)
3293         {
3294                         if (!mesh->sidetotals[r_shadow_shadowmapside])
3295                                 continue;
3296             r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
3297             R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3298             R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3299         }
3300         CHECKGLERROR
3301     }
3302         else if (r_refdef.scene.worldentity->model)
3303                 r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3304
3305         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3306 }
3307
3308 void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
3309 {
3310         qboolean zpass = false;
3311         shadowmesh_t *mesh;
3312         int t, tend;
3313         int surfacelistindex;
3314         msurface_t *surface;
3315
3316         RSurf_ActiveWorldEntity();
3317
3318         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3319         {
3320                 CHECKGLERROR
3321                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
3322                 {
3323                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3324                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
3325                 }
3326                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
3327                 for (;mesh;mesh = mesh->next)
3328                 {
3329                         r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
3330                         R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3331                         GL_LockArrays(0, mesh->numverts);
3332                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
3333                         {
3334                                 // increment stencil if frontface is infront of depthbuffer
3335                                 GL_CullFace(r_refdef.view.cullface_back);
3336                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
3337                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3338                                 // decrement stencil if backface is infront of depthbuffer
3339                                 GL_CullFace(r_refdef.view.cullface_front);
3340                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
3341                         }
3342                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
3343                         {
3344                                 // decrement stencil if backface is behind depthbuffer
3345                                 GL_CullFace(r_refdef.view.cullface_front);
3346                                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
3347                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3348                                 // increment stencil if frontface is behind depthbuffer
3349                                 GL_CullFace(r_refdef.view.cullface_back);
3350                                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
3351                         }
3352                         R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3353                         GL_LockArrays(0, 0);
3354                 }
3355                 CHECKGLERROR
3356         }
3357         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh && r_shadow_culltriangles.integer)
3358         {
3359                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
3360                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3361                 {
3362                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
3363                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
3364                                 if (CHECKPVSBIT(trispvs, t))
3365                                         shadowmarklist[numshadowmark++] = t;
3366                 }
3367                 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);
3368         }
3369         else if (numsurfaces)
3370                 r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3371
3372         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3373 }
3374
3375 void R_Shadow_DrawEntityShadow(entity_render_t *ent)
3376 {
3377         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
3378         vec_t relativeshadowradius;
3379         RSurf_ActiveModelEntity(ent, false, false);
3380         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
3381         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
3382         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
3383         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
3384         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
3385         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
3386         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
3387         relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
3388         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D)
3389         {
3390                 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
3391         }
3392         else
3393                 ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
3394         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3395 }
3396
3397 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
3398 {
3399         // set up properties for rendering light onto this entity
3400         RSurf_ActiveModelEntity(ent, true, true);
3401         GL_AlphaTest(false);
3402         Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
3403         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3404         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3405         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3406         switch(r_shadow_lightingrendermode)
3407         {
3408         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
3409                 R_Mesh_TexMatrix(3, &rsurface.entitytolight);
3410                 break;
3411         default:
3412                 break;
3413         }
3414 }
3415
3416 void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
3417 {
3418         if (!r_refdef.scene.worldmodel->DrawLight)
3419                 return;
3420
3421         // set up properties for rendering light onto this entity
3422         RSurf_ActiveWorldEntity();
3423         GL_AlphaTest(false);
3424         rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
3425         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3426         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3427         VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3428         switch(r_shadow_lightingrendermode)
3429         {
3430         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
3431                 R_Mesh_TexMatrix(3, &rsurface.entitytolight);
3432                 break;
3433         default:
3434                 break;
3435         }
3436
3437         r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, trispvs);
3438
3439         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3440 }
3441
3442 void R_Shadow_DrawEntityLight(entity_render_t *ent)
3443 {
3444         dp_model_t *model = ent->model;
3445         if (!model->DrawLight)
3446                 return;
3447
3448         R_Shadow_SetupEntityLight(ent);
3449
3450         model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
3451
3452         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3453 }
3454
3455 void R_CacheRTLight(rtlight_t *rtlight)