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