]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - r_shadow.c
update CG shader for shadowmaportho
[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 extern void R_Shadow_EditLights_Init(void);
144
145 typedef enum r_shadow_rendermode_e
146 {
147         R_SHADOW_RENDERMODE_NONE,
148         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
149         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
150         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
151         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
152         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
153         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
154         R_SHADOW_RENDERMODE_LIGHT_VERTEX,
155         R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN,
156         R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN,
157         R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN,
158         R_SHADOW_RENDERMODE_LIGHT_GLSL,
159         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
160         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
161         R_SHADOW_RENDERMODE_SHADOWMAP2D,
162         R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
163         R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
164 }
165 r_shadow_rendermode_t;
166
167 typedef enum r_shadow_shadowmode_e
168 {
169     R_SHADOW_SHADOWMODE_STENCIL,
170     R_SHADOW_SHADOWMODE_SHADOWMAP2D,
171     R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
172     R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
173 }
174 r_shadow_shadowmode_t;
175
176 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
177 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
178 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
179 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
180 qboolean r_shadow_usingshadowmaprect;
181 qboolean r_shadow_usingshadowmap2d;
182 qboolean r_shadow_usingshadowmapcube;
183 qboolean r_shadow_usingshadowmaportho;
184 int r_shadow_shadowmapside;
185 float r_shadow_shadowmap_texturescale[2];
186 float r_shadow_shadowmap_parameters[4];
187 #if 0
188 int r_shadow_drawbuffer;
189 int r_shadow_readbuffer;
190 #endif
191 int r_shadow_cullface_front, r_shadow_cullface_back;
192 GLuint r_shadow_fborectangle;
193 GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
194 GLuint r_shadow_fbo2d;
195 r_shadow_shadowmode_t r_shadow_shadowmode;
196 int r_shadow_shadowmapfilterquality;
197 int r_shadow_shadowmaptexturetype;
198 int r_shadow_shadowmapdepthbits;
199 int r_shadow_shadowmapmaxsize;
200 qboolean r_shadow_shadowmapvsdct;
201 qboolean r_shadow_shadowmapsampler;
202 int r_shadow_shadowmappcf;
203 int r_shadow_shadowmapborder;
204 matrix4x4_t r_shadow_shadowmapmatrix;
205 int r_shadow_lightscissor[4];
206 qboolean r_shadow_usingdeferredprepass;
207
208 int maxshadowtriangles;
209 int *shadowelements;
210
211 int maxshadowvertices;
212 float *shadowvertex3f;
213
214 int maxshadowmark;
215 int numshadowmark;
216 int *shadowmark;
217 int *shadowmarklist;
218 int shadowmarkcount;
219
220 int maxshadowsides;
221 int numshadowsides;
222 unsigned char *shadowsides;
223 int *shadowsideslist;
224
225 int maxvertexupdate;
226 int *vertexupdate;
227 int *vertexremap;
228 int vertexupdatenum;
229
230 int r_shadow_buffer_numleafpvsbytes;
231 unsigned char *r_shadow_buffer_visitingleafpvs;
232 unsigned char *r_shadow_buffer_leafpvs;
233 int *r_shadow_buffer_leaflist;
234
235 int r_shadow_buffer_numsurfacepvsbytes;
236 unsigned char *r_shadow_buffer_surfacepvs;
237 int *r_shadow_buffer_surfacelist;
238 unsigned char *r_shadow_buffer_surfacesides;
239
240 int r_shadow_buffer_numshadowtrispvsbytes;
241 unsigned char *r_shadow_buffer_shadowtrispvs;
242 int r_shadow_buffer_numlighttrispvsbytes;
243 unsigned char *r_shadow_buffer_lighttrispvs;
244
245 rtexturepool_t *r_shadow_texturepool;
246 rtexture_t *r_shadow_attenuationgradienttexture;
247 rtexture_t *r_shadow_attenuation2dtexture;
248 rtexture_t *r_shadow_attenuation3dtexture;
249 skinframe_t *r_shadow_lightcorona;
250 rtexture_t *r_shadow_shadowmaprectangletexture;
251 rtexture_t *r_shadow_shadowmap2dtexture;
252 rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
253 rtexture_t *r_shadow_shadowmapvsdcttexture;
254 int r_shadow_shadowmapsize; // changes for each light based on distance
255 int r_shadow_shadowmaplod; // changes for each light based on distance
256
257 GLuint r_shadow_prepassgeometryfbo;
258 GLuint r_shadow_prepasslightingfbo;
259 int r_shadow_prepass_width;
260 int r_shadow_prepass_height;
261 rtexture_t *r_shadow_prepassgeometrydepthtexture;
262 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
263 rtexture_t *r_shadow_prepasslightingdiffusetexture;
264 rtexture_t *r_shadow_prepasslightingspeculartexture;
265
266 // lights are reloaded when this changes
267 char r_shadow_mapname[MAX_QPATH];
268
269 // used only for light filters (cubemaps)
270 rtexturepool_t *r_shadow_filters_texturepool;
271
272 static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
273
274 cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
275 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
276 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
277 cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
278 cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "2", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
279 //cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
280 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
281 cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
282 cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
283 cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
284 cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
285 cvar_t r_shadow_gloss2exponent = {0, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
286 cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
287 cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
288 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
289 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
290 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
291 cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
292 cvar_t r_shadow_frontsidecasting = {0, "r_shadow_frontsidecasting", "1", "whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)"};
293 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
294 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
295 cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
296 cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
297 cvar_t r_shadow_realtime_world = {CVAR_SAVE, "r_shadow_realtime_world", "0", "enables rendering of full world lighting (whether loaded from the map, or a .rtlights file, or a .ent file, or a .lights file produced by hlight)"};
298 cvar_t r_shadow_realtime_world_lightmaps = {CVAR_SAVE, "r_shadow_realtime_world_lightmaps", "0", "brightness to render lightmaps when using full world lighting, try 0.5 for a tenebrae-like appearance"};
299 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
300 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
301 cvar_t r_shadow_realtime_world_compileshadow = {0, "r_shadow_realtime_world_compileshadow", "1", "enables compilation of shadows from world lights for higher performance rendering"};
302 cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
303 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "0", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
304 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
305 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
306 cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
307 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
308 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
309 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
310 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
311 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
312 cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
313 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
314 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
315 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
316 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
317 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
318 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
319 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
320 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
321 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
322 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect OpenGL 2.0 render path)"};
323 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
324 cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksm the proportion of hidden pixels controls corona intensity"};
325 cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
326 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
327 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
328 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
329 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
330 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
331 cvar_t r_editlights_cursorpushback = {0, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
332 cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
333 cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
334 cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
335
336 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
337 #define ATTENTABLESIZE 256
338 // 1D gradient, 2D circle and 3D sphere attenuation textures
339 #define ATTEN1DSIZE 32
340 #define ATTEN2DSIZE 64
341 #define ATTEN3DSIZE 32
342
343 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
344 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
345 static float r_shadow_attentable[ATTENTABLESIZE+1];
346
347 rtlight_t *r_shadow_compilingrtlight;
348 static memexpandablearray_t r_shadow_worldlightsarray;
349 dlight_t *r_shadow_selectedlight;
350 dlight_t r_shadow_bufferlight;
351 vec3_t r_editlights_cursorlocation;
352
353 extern int con_vislines;
354
355 void R_Shadow_UncompileWorldLights(void);
356 void R_Shadow_ClearWorldLights(void);
357 void R_Shadow_SaveWorldLights(void);
358 void R_Shadow_LoadWorldLights(void);
359 void R_Shadow_LoadLightsFile(void);
360 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
361 void R_Shadow_EditLights_Reload_f(void);
362 void R_Shadow_ValidateCvars(void);
363 static void R_Shadow_MakeTextures(void);
364
365 #define EDLIGHTSPRSIZE                  8
366 skinframe_t *r_editlights_sprcursor;
367 skinframe_t *r_editlights_sprlight;
368 skinframe_t *r_editlights_sprnoshadowlight;
369 skinframe_t *r_editlights_sprcubemaplight;
370 skinframe_t *r_editlights_sprcubemapnoshadowlight;
371 skinframe_t *r_editlights_sprselection;
372
373 void R_Shadow_SetShadowMode(void)
374 {
375         r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
376         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
377         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
378         r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
379         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
380         r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
381         r_shadow_shadowmaplod = -1;
382         r_shadow_shadowmapsize = 0;
383         r_shadow_shadowmapsampler = false;
384         r_shadow_shadowmappcf = 0;
385         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
386         switch(vid.renderpath)
387         {
388         case RENDERPATH_GL20:
389         case RENDERPATH_CGGL:
390                 if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
391                 {
392                         if(r_shadow_shadowmapfilterquality < 0)
393                         {
394                                 if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
395                                         r_shadow_shadowmappcf = 1;
396                                 else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) 
397                                 {
398                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
399                                         r_shadow_shadowmappcf = 1;
400                                 }
401                                 else if(strstr(gl_vendor, "ATI")) 
402                                         r_shadow_shadowmappcf = 1;
403                                 else 
404                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
405                         }
406                         else 
407                         {
408                                 switch (r_shadow_shadowmapfilterquality)
409                                 {
410                                 case 1:
411                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
412                                         break;
413                                 case 2:
414                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
415                                         r_shadow_shadowmappcf = 1;
416                                         break;
417                                 case 3:
418                                         r_shadow_shadowmappcf = 1;
419                                         break;
420                                 case 4:
421                                         r_shadow_shadowmappcf = 2;
422                                         break;
423                                 }
424                         }
425                         switch (r_shadow_shadowmaptexturetype)
426                         {
427                         case 0:
428                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
429                                 break;
430                         case 1:
431                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
432                                 break;
433                         case 2:
434                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
435                                 break;
436                         default:
437                                 if((vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
438                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
439                                 else if(vid.support.arb_texture_rectangle) 
440                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
441                                 else
442                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
443                                 break;
444                         }
445                 }
446                 break;
447         case RENDERPATH_GL13:
448                 break;
449         case RENDERPATH_GL11:
450                 break;
451         }
452 }
453
454 qboolean R_Shadow_ShadowMappingEnabled(void)
455 {
456         switch (r_shadow_shadowmode)
457         {
458         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
459         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
460         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
461                 return true;
462         default:
463                 return false;
464         }
465 }
466
467 void R_Shadow_FreeShadowMaps(void)
468 {
469         int i;
470
471         R_Shadow_SetShadowMode();
472
473         if (!vid.support.ext_framebuffer_object || !vid.support.arb_fragment_shader)
474                 return;
475
476         CHECKGLERROR
477
478         if (r_shadow_fborectangle)
479                 qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
480         r_shadow_fborectangle = 0;
481
482         if (r_shadow_fbo2d)
483                 qglDeleteFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
484         r_shadow_fbo2d = 0;
485         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
486                 if (r_shadow_fbocubeside[i])
487                         qglDeleteFramebuffersEXT(1, &r_shadow_fbocubeside[i]);CHECKGLERROR
488         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
489
490         if (r_shadow_shadowmaprectangletexture)
491                 R_FreeTexture(r_shadow_shadowmaprectangletexture);
492         r_shadow_shadowmaprectangletexture = NULL;
493
494         if (r_shadow_shadowmap2dtexture)
495                 R_FreeTexture(r_shadow_shadowmap2dtexture);
496         r_shadow_shadowmap2dtexture = NULL;
497
498         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
499                 if (r_shadow_shadowmapcubetexture[i])
500                         R_FreeTexture(r_shadow_shadowmapcubetexture[i]);
501         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
502
503         if (r_shadow_shadowmapvsdcttexture)
504                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
505         r_shadow_shadowmapvsdcttexture = NULL;
506
507         CHECKGLERROR
508
509         r_shadow_usingshadowmaportho = false;
510 }
511
512 void r_shadow_start(void)
513 {
514         // allocate vertex processing arrays
515         r_shadow_attenuationgradienttexture = NULL;
516         r_shadow_attenuation2dtexture = NULL;
517         r_shadow_attenuation3dtexture = NULL;
518         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
519         r_shadow_shadowmaprectangletexture = NULL;
520         r_shadow_shadowmap2dtexture = NULL;
521         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
522         r_shadow_shadowmapvsdcttexture = NULL;
523         r_shadow_shadowmapmaxsize = 0;
524         r_shadow_shadowmapsize = 0;
525         r_shadow_shadowmaplod = 0;
526         r_shadow_shadowmapfilterquality = -1;
527         r_shadow_shadowmaptexturetype = -1;
528         r_shadow_shadowmapdepthbits = 0;
529         r_shadow_shadowmapvsdct = false;
530         r_shadow_shadowmapsampler = false;
531         r_shadow_shadowmappcf = 0;
532         r_shadow_fborectangle = 0;
533         r_shadow_fbo2d = 0;
534         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
535
536         R_Shadow_FreeShadowMaps();
537
538         r_shadow_texturepool = NULL;
539         r_shadow_filters_texturepool = NULL;
540         R_Shadow_ValidateCvars();
541         R_Shadow_MakeTextures();
542         maxshadowtriangles = 0;
543         shadowelements = NULL;
544         maxshadowvertices = 0;
545         shadowvertex3f = NULL;
546         maxvertexupdate = 0;
547         vertexupdate = NULL;
548         vertexremap = NULL;
549         vertexupdatenum = 0;
550         maxshadowmark = 0;
551         numshadowmark = 0;
552         shadowmark = NULL;
553         shadowmarklist = NULL;
554         shadowmarkcount = 0;
555         maxshadowsides = 0;
556         numshadowsides = 0;
557         shadowsides = NULL;
558         shadowsideslist = NULL;
559         r_shadow_buffer_numleafpvsbytes = 0;
560         r_shadow_buffer_visitingleafpvs = NULL;
561         r_shadow_buffer_leafpvs = NULL;
562         r_shadow_buffer_leaflist = NULL;
563         r_shadow_buffer_numsurfacepvsbytes = 0;
564         r_shadow_buffer_surfacepvs = NULL;
565         r_shadow_buffer_surfacelist = NULL;
566         r_shadow_buffer_surfacesides = NULL;
567         r_shadow_buffer_numshadowtrispvsbytes = 0;
568         r_shadow_buffer_shadowtrispvs = NULL;
569         r_shadow_buffer_numlighttrispvsbytes = 0;
570         r_shadow_buffer_lighttrispvs = NULL;
571
572         r_shadow_usingdeferredprepass = false;
573         r_shadow_prepass_width = r_shadow_prepass_height = 0;
574 }
575
576 static void R_Shadow_FreeDeferred(void);
577 void r_shadow_shutdown(void)
578 {
579         CHECKGLERROR
580         R_Shadow_UncompileWorldLights();
581
582         R_Shadow_FreeShadowMaps();
583
584         r_shadow_usingdeferredprepass = false;
585         if (r_shadow_prepass_width)
586                 R_Shadow_FreeDeferred();
587         r_shadow_prepass_width = r_shadow_prepass_height = 0;
588
589         CHECKGLERROR
590         r_shadow_attenuationgradienttexture = NULL;
591         r_shadow_attenuation2dtexture = NULL;
592         r_shadow_attenuation3dtexture = NULL;
593         R_FreeTexturePool(&r_shadow_texturepool);
594         R_FreeTexturePool(&r_shadow_filters_texturepool);
595         maxshadowtriangles = 0;
596         if (shadowelements)
597                 Mem_Free(shadowelements);
598         shadowelements = NULL;
599         if (shadowvertex3f)
600                 Mem_Free(shadowvertex3f);
601         shadowvertex3f = NULL;
602         maxvertexupdate = 0;
603         if (vertexupdate)
604                 Mem_Free(vertexupdate);
605         vertexupdate = NULL;
606         if (vertexremap)
607                 Mem_Free(vertexremap);
608         vertexremap = NULL;
609         vertexupdatenum = 0;
610         maxshadowmark = 0;
611         numshadowmark = 0;
612         if (shadowmark)
613                 Mem_Free(shadowmark);
614         shadowmark = NULL;
615         if (shadowmarklist)
616                 Mem_Free(shadowmarklist);
617         shadowmarklist = NULL;
618         shadowmarkcount = 0;
619         maxshadowsides = 0;
620         numshadowsides = 0;
621         if (shadowsides)
622                 Mem_Free(shadowsides);
623         shadowsides = NULL;
624         if (shadowsideslist)
625                 Mem_Free(shadowsideslist);
626         shadowsideslist = NULL;
627         r_shadow_buffer_numleafpvsbytes = 0;
628         if (r_shadow_buffer_visitingleafpvs)
629                 Mem_Free(r_shadow_buffer_visitingleafpvs);
630         r_shadow_buffer_visitingleafpvs = NULL;
631         if (r_shadow_buffer_leafpvs)
632                 Mem_Free(r_shadow_buffer_leafpvs);
633         r_shadow_buffer_leafpvs = NULL;
634         if (r_shadow_buffer_leaflist)
635                 Mem_Free(r_shadow_buffer_leaflist);
636         r_shadow_buffer_leaflist = NULL;
637         r_shadow_buffer_numsurfacepvsbytes = 0;
638         if (r_shadow_buffer_surfacepvs)
639                 Mem_Free(r_shadow_buffer_surfacepvs);
640         r_shadow_buffer_surfacepvs = NULL;
641         if (r_shadow_buffer_surfacelist)
642                 Mem_Free(r_shadow_buffer_surfacelist);
643         r_shadow_buffer_surfacelist = NULL;
644         if (r_shadow_buffer_surfacesides)
645                 Mem_Free(r_shadow_buffer_surfacesides);
646         r_shadow_buffer_surfacesides = NULL;
647         r_shadow_buffer_numshadowtrispvsbytes = 0;
648         if (r_shadow_buffer_shadowtrispvs)
649                 Mem_Free(r_shadow_buffer_shadowtrispvs);
650         r_shadow_buffer_numlighttrispvsbytes = 0;
651         if (r_shadow_buffer_lighttrispvs)
652                 Mem_Free(r_shadow_buffer_lighttrispvs);
653 }
654
655 void r_shadow_newmap(void)
656 {
657         if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
658         if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
659         if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
660         if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
661         if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
662         if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
663         if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
664         if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
665                 R_Shadow_EditLights_Reload_f();
666 }
667
668 void R_Shadow_Init(void)
669 {
670         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
671         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
672         Cvar_RegisterVariable(&r_shadow_usenormalmap);
673         Cvar_RegisterVariable(&r_shadow_debuglight);
674         Cvar_RegisterVariable(&r_shadow_deferred);
675         Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
676 //      Cvar_RegisterVariable(&r_shadow_deferred_fp);
677         Cvar_RegisterVariable(&r_shadow_gloss);
678         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
679         Cvar_RegisterVariable(&r_shadow_glossintensity);
680         Cvar_RegisterVariable(&r_shadow_glossexponent);
681         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
682         Cvar_RegisterVariable(&r_shadow_glossexact);
683         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
684         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
685         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
686         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
687         Cvar_RegisterVariable(&r_shadow_projectdistance);
688         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
689         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
690         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
691         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
692         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
693         Cvar_RegisterVariable(&r_shadow_realtime_world);
694         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
695         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
696         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
697         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
698         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
699         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
700         Cvar_RegisterVariable(&r_shadow_scissor);
701         Cvar_RegisterVariable(&r_shadow_shadowmapping);
702         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
703         Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
704         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
705         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
706         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
707         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
708         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
709 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
710 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
711         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
712         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
713         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
714         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
715         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
716         Cvar_RegisterVariable(&r_shadow_polygonfactor);
717         Cvar_RegisterVariable(&r_shadow_polygonoffset);
718         Cvar_RegisterVariable(&r_shadow_texture3d);
719         Cvar_RegisterVariable(&r_coronas);
720         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
721         Cvar_RegisterVariable(&r_coronas_occlusionquery);
722         Cvar_RegisterVariable(&gl_flashblend);
723         Cvar_RegisterVariable(&gl_ext_separatestencil);
724         Cvar_RegisterVariable(&gl_ext_stenciltwoside);
725         if (gamemode == GAME_TENEBRAE)
726         {
727                 Cvar_SetValue("r_shadow_gloss", 2);
728                 Cvar_SetValue("r_shadow_bumpscale_basetexture", 4);
729         }
730         R_Shadow_EditLights_Init();
731         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
732         maxshadowtriangles = 0;
733         shadowelements = NULL;
734         maxshadowvertices = 0;
735         shadowvertex3f = NULL;
736         maxvertexupdate = 0;
737         vertexupdate = NULL;
738         vertexremap = NULL;
739         vertexupdatenum = 0;
740         maxshadowmark = 0;
741         numshadowmark = 0;
742         shadowmark = NULL;
743         shadowmarklist = NULL;
744         shadowmarkcount = 0;
745         maxshadowsides = 0;
746         numshadowsides = 0;
747         shadowsides = NULL;
748         shadowsideslist = NULL;
749         r_shadow_buffer_numleafpvsbytes = 0;
750         r_shadow_buffer_visitingleafpvs = NULL;
751         r_shadow_buffer_leafpvs = NULL;
752         r_shadow_buffer_leaflist = NULL;
753         r_shadow_buffer_numsurfacepvsbytes = 0;
754         r_shadow_buffer_surfacepvs = NULL;
755         r_shadow_buffer_surfacelist = NULL;
756         r_shadow_buffer_surfacesides = NULL;
757         r_shadow_buffer_shadowtrispvs = NULL;
758         r_shadow_buffer_lighttrispvs = NULL;
759         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
760 }
761
762 matrix4x4_t matrix_attenuationxyz =
763 {
764         {
765                 {0.5, 0.0, 0.0, 0.5},
766                 {0.0, 0.5, 0.0, 0.5},
767                 {0.0, 0.0, 0.5, 0.5},
768                 {0.0, 0.0, 0.0, 1.0}
769         }
770 };
771
772 matrix4x4_t matrix_attenuationz =
773 {
774         {
775                 {0.0, 0.0, 0.5, 0.5},
776                 {0.0, 0.0, 0.0, 0.5},
777                 {0.0, 0.0, 0.0, 0.5},
778                 {0.0, 0.0, 0.0, 1.0}
779         }
780 };
781
782 void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
783 {
784         numvertices = ((numvertices + 255) & ~255) * vertscale;
785         numtriangles = ((numtriangles + 255) & ~255) * triscale;
786         // make sure shadowelements is big enough for this volume
787         if (maxshadowtriangles < numtriangles)
788         {
789                 maxshadowtriangles = numtriangles;
790                 if (shadowelements)
791                         Mem_Free(shadowelements);
792                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
793         }
794         // make sure shadowvertex3f is big enough for this volume
795         if (maxshadowvertices < numvertices)
796         {
797                 maxshadowvertices = numvertices;
798                 if (shadowvertex3f)
799                         Mem_Free(shadowvertex3f);
800                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
801         }
802 }
803
804 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
805 {
806         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
807         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
808         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
809         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
810         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
811         {
812                 if (r_shadow_buffer_visitingleafpvs)
813                         Mem_Free(r_shadow_buffer_visitingleafpvs);
814                 if (r_shadow_buffer_leafpvs)
815                         Mem_Free(r_shadow_buffer_leafpvs);
816                 if (r_shadow_buffer_leaflist)
817                         Mem_Free(r_shadow_buffer_leaflist);
818                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
819                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
820                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
821                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
822         }
823         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
824         {
825                 if (r_shadow_buffer_surfacepvs)
826                         Mem_Free(r_shadow_buffer_surfacepvs);
827                 if (r_shadow_buffer_surfacelist)
828                         Mem_Free(r_shadow_buffer_surfacelist);
829                 if (r_shadow_buffer_surfacesides)
830                         Mem_Free(r_shadow_buffer_surfacesides);
831                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
832                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
833                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
834                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
835         }
836         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
837         {
838                 if (r_shadow_buffer_shadowtrispvs)
839                         Mem_Free(r_shadow_buffer_shadowtrispvs);
840                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
841                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
842         }
843         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
844         {
845                 if (r_shadow_buffer_lighttrispvs)
846                         Mem_Free(r_shadow_buffer_lighttrispvs);
847                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
848                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
849         }
850 }
851
852 void R_Shadow_PrepareShadowMark(int numtris)
853 {
854         // make sure shadowmark is big enough for this volume
855         if (maxshadowmark < numtris)
856         {
857                 maxshadowmark = numtris;
858                 if (shadowmark)
859                         Mem_Free(shadowmark);
860                 if (shadowmarklist)
861                         Mem_Free(shadowmarklist);
862                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
863                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
864                 shadowmarkcount = 0;
865         }
866         shadowmarkcount++;
867         // if shadowmarkcount wrapped we clear the array and adjust accordingly
868         if (shadowmarkcount == 0)
869         {
870                 shadowmarkcount = 1;
871                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
872         }
873         numshadowmark = 0;
874 }
875
876 void R_Shadow_PrepareShadowSides(int numtris)
877 {
878     if (maxshadowsides < numtris)
879     {
880         maxshadowsides = numtris;
881         if (shadowsides)
882                         Mem_Free(shadowsides);
883                 if (shadowsideslist)
884                         Mem_Free(shadowsideslist);
885                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
886                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
887         }
888         numshadowsides = 0;
889 }
890
891 static int R_Shadow_ConstructShadowVolume_ZFail(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
892 {
893         int i, j;
894         int outtriangles = 0, outvertices = 0;
895         const int *element;
896         const float *vertex;
897         float ratio, direction[3], projectvector[3];
898
899         if (projectdirection)
900                 VectorScale(projectdirection, projectdistance, projectvector);
901         else
902                 VectorClear(projectvector);
903
904         // create the vertices
905         if (projectdirection)
906         {
907                 for (i = 0;i < numshadowmarktris;i++)
908                 {
909                         element = inelement3i + shadowmarktris[i] * 3;
910                         for (j = 0;j < 3;j++)
911                         {
912                                 if (vertexupdate[element[j]] != vertexupdatenum)
913                                 {
914                                         vertexupdate[element[j]] = vertexupdatenum;
915                                         vertexremap[element[j]] = outvertices;
916                                         vertex = invertex3f + element[j] * 3;
917                                         // project one copy of the vertex according to projectvector
918                                         VectorCopy(vertex, outvertex3f);
919                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
920                                         outvertex3f += 6;
921                                         outvertices += 2;
922                                 }
923                         }
924                 }
925         }
926         else
927         {
928                 for (i = 0;i < numshadowmarktris;i++)
929                 {
930                         element = inelement3i + shadowmarktris[i] * 3;
931                         for (j = 0;j < 3;j++)
932                         {
933                                 if (vertexupdate[element[j]] != vertexupdatenum)
934                                 {
935                                         vertexupdate[element[j]] = vertexupdatenum;
936                                         vertexremap[element[j]] = outvertices;
937                                         vertex = invertex3f + element[j] * 3;
938                                         // project one copy of the vertex to the sphere radius of the light
939                                         // (FIXME: would projecting it to the light box be better?)
940                                         VectorSubtract(vertex, projectorigin, direction);
941                                         ratio = projectdistance / VectorLength(direction);
942                                         VectorCopy(vertex, outvertex3f);
943                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
944                                         outvertex3f += 6;
945                                         outvertices += 2;
946                                 }
947                         }
948                 }
949         }
950
951         if (r_shadow_frontsidecasting.integer)
952         {
953                 for (i = 0;i < numshadowmarktris;i++)
954                 {
955                         int remappedelement[3];
956                         int markindex;
957                         const int *neighbortriangle;
958
959                         markindex = shadowmarktris[i] * 3;
960                         element = inelement3i + markindex;
961                         neighbortriangle = inneighbor3i + markindex;
962                         // output the front and back triangles
963                         outelement3i[0] = vertexremap[element[0]];
964                         outelement3i[1] = vertexremap[element[1]];
965                         outelement3i[2] = vertexremap[element[2]];
966                         outelement3i[3] = vertexremap[element[2]] + 1;
967                         outelement3i[4] = vertexremap[element[1]] + 1;
968                         outelement3i[5] = vertexremap[element[0]] + 1;
969
970                         outelement3i += 6;
971                         outtriangles += 2;
972                         // output the sides (facing outward from this triangle)
973                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
974                         {
975                                 remappedelement[0] = vertexremap[element[0]];
976                                 remappedelement[1] = vertexremap[element[1]];
977                                 outelement3i[0] = remappedelement[1];
978                                 outelement3i[1] = remappedelement[0];
979                                 outelement3i[2] = remappedelement[0] + 1;
980                                 outelement3i[3] = remappedelement[1];
981                                 outelement3i[4] = remappedelement[0] + 1;
982                                 outelement3i[5] = remappedelement[1] + 1;
983
984                                 outelement3i += 6;
985                                 outtriangles += 2;
986                         }
987                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
988                         {
989                                 remappedelement[1] = vertexremap[element[1]];
990                                 remappedelement[2] = vertexremap[element[2]];
991                                 outelement3i[0] = remappedelement[2];
992                                 outelement3i[1] = remappedelement[1];
993                                 outelement3i[2] = remappedelement[1] + 1;
994                                 outelement3i[3] = remappedelement[2];
995                                 outelement3i[4] = remappedelement[1] + 1;
996                                 outelement3i[5] = remappedelement[2] + 1;
997
998                                 outelement3i += 6;
999                                 outtriangles += 2;
1000                         }
1001                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1002                         {
1003                                 remappedelement[0] = vertexremap[element[0]];
1004                                 remappedelement[2] = vertexremap[element[2]];
1005                                 outelement3i[0] = remappedelement[0];
1006                                 outelement3i[1] = remappedelement[2];
1007                                 outelement3i[2] = remappedelement[2] + 1;
1008                                 outelement3i[3] = remappedelement[0];
1009                                 outelement3i[4] = remappedelement[2] + 1;
1010                                 outelement3i[5] = remappedelement[0] + 1;
1011
1012                                 outelement3i += 6;
1013                                 outtriangles += 2;
1014                         }
1015                 }
1016         }
1017         else
1018         {
1019                 for (i = 0;i < numshadowmarktris;i++)
1020                 {
1021                         int remappedelement[3];
1022                         int markindex;
1023                         const int *neighbortriangle;
1024
1025                         markindex = shadowmarktris[i] * 3;
1026                         element = inelement3i + markindex;
1027                         neighbortriangle = inneighbor3i + markindex;
1028                         // output the front and back triangles
1029                         outelement3i[0] = vertexremap[element[2]];
1030                         outelement3i[1] = vertexremap[element[1]];
1031                         outelement3i[2] = vertexremap[element[0]];
1032                         outelement3i[3] = vertexremap[element[0]] + 1;
1033                         outelement3i[4] = vertexremap[element[1]] + 1;
1034                         outelement3i[5] = vertexremap[element[2]] + 1;
1035
1036                         outelement3i += 6;
1037                         outtriangles += 2;
1038                         // output the sides (facing outward from this triangle)
1039                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1040                         {
1041                                 remappedelement[0] = vertexremap[element[0]];
1042                                 remappedelement[1] = vertexremap[element[1]];
1043                                 outelement3i[0] = remappedelement[0];
1044                                 outelement3i[1] = remappedelement[1];
1045                                 outelement3i[2] = remappedelement[1] + 1;
1046                                 outelement3i[3] = remappedelement[0];
1047                                 outelement3i[4] = remappedelement[1] + 1;
1048                                 outelement3i[5] = remappedelement[0] + 1;
1049
1050                                 outelement3i += 6;
1051                                 outtriangles += 2;
1052                         }
1053                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1054                         {
1055                                 remappedelement[1] = vertexremap[element[1]];
1056                                 remappedelement[2] = vertexremap[element[2]];
1057                                 outelement3i[0] = remappedelement[1];
1058                                 outelement3i[1] = remappedelement[2];
1059                                 outelement3i[2] = remappedelement[2] + 1;
1060                                 outelement3i[3] = remappedelement[1];
1061                                 outelement3i[4] = remappedelement[2] + 1;
1062                                 outelement3i[5] = remappedelement[1] + 1;
1063
1064                                 outelement3i += 6;
1065                                 outtriangles += 2;
1066                         }
1067                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1068                         {
1069                                 remappedelement[0] = vertexremap[element[0]];
1070                                 remappedelement[2] = vertexremap[element[2]];
1071                                 outelement3i[0] = remappedelement[2];
1072                                 outelement3i[1] = remappedelement[0];
1073                                 outelement3i[2] = remappedelement[0] + 1;
1074                                 outelement3i[3] = remappedelement[2];
1075                                 outelement3i[4] = remappedelement[0] + 1;
1076                                 outelement3i[5] = remappedelement[2] + 1;
1077
1078                                 outelement3i += 6;
1079                                 outtriangles += 2;
1080                         }
1081                 }
1082         }
1083         if (outnumvertices)
1084                 *outnumvertices = outvertices;
1085         return outtriangles;
1086 }
1087
1088 static int R_Shadow_ConstructShadowVolume_ZPass(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
1089 {
1090         int i, j, k;
1091         int outtriangles = 0, outvertices = 0;
1092         const int *element;
1093         const float *vertex;
1094         float ratio, direction[3], projectvector[3];
1095         qboolean side[4];
1096
1097         if (projectdirection)
1098                 VectorScale(projectdirection, projectdistance, projectvector);
1099         else
1100                 VectorClear(projectvector);
1101
1102         for (i = 0;i < numshadowmarktris;i++)
1103         {
1104                 int remappedelement[3];
1105                 int markindex;
1106                 const int *neighbortriangle;
1107
1108                 markindex = shadowmarktris[i] * 3;
1109                 neighbortriangle = inneighbor3i + markindex;
1110                 side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
1111                 side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
1112                 side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
1113                 if (side[0] + side[1] + side[2] == 0)
1114                         continue;
1115
1116                 side[3] = side[0];
1117                 element = inelement3i + markindex;
1118
1119                 // create the vertices
1120                 for (j = 0;j < 3;j++)
1121                 {
1122                         if (side[j] + side[j+1] == 0)
1123                                 continue;
1124                         k = element[j];
1125                         if (vertexupdate[k] != vertexupdatenum)
1126                         {
1127                                 vertexupdate[k] = vertexupdatenum;
1128                                 vertexremap[k] = outvertices;
1129                                 vertex = invertex3f + k * 3;
1130                                 VectorCopy(vertex, outvertex3f);
1131                                 if (projectdirection)
1132                                 {
1133                                         // project one copy of the vertex according to projectvector
1134                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1135                                 }
1136                                 else
1137                                 {
1138                                         // project one copy of the vertex to the sphere radius of the light
1139                                         // (FIXME: would projecting it to the light box be better?)
1140                                         VectorSubtract(vertex, projectorigin, direction);
1141                                         ratio = projectdistance / VectorLength(direction);
1142                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1143                                 }
1144                                 outvertex3f += 6;
1145                                 outvertices += 2;
1146                         }
1147                 }
1148
1149                 // output the sides (facing outward from this triangle)
1150                 if (!side[0])
1151                 {
1152                         remappedelement[0] = vertexremap[element[0]];
1153                         remappedelement[1] = vertexremap[element[1]];
1154                         outelement3i[0] = remappedelement[1];
1155                         outelement3i[1] = remappedelement[0];
1156                         outelement3i[2] = remappedelement[0] + 1;
1157                         outelement3i[3] = remappedelement[1];
1158                         outelement3i[4] = remappedelement[0] + 1;
1159                         outelement3i[5] = remappedelement[1] + 1;
1160
1161                         outelement3i += 6;
1162                         outtriangles += 2;
1163                 }
1164                 if (!side[1])
1165                 {
1166                         remappedelement[1] = vertexremap[element[1]];
1167                         remappedelement[2] = vertexremap[element[2]];
1168                         outelement3i[0] = remappedelement[2];
1169                         outelement3i[1] = remappedelement[1];
1170                         outelement3i[2] = remappedelement[1] + 1;
1171                         outelement3i[3] = remappedelement[2];
1172                         outelement3i[4] = remappedelement[1] + 1;
1173                         outelement3i[5] = remappedelement[2] + 1;
1174
1175                         outelement3i += 6;
1176                         outtriangles += 2;
1177                 }
1178                 if (!side[2])
1179                 {
1180                         remappedelement[0] = vertexremap[element[0]];
1181                         remappedelement[2] = vertexremap[element[2]];
1182                         outelement3i[0] = remappedelement[0];
1183                         outelement3i[1] = remappedelement[2];
1184                         outelement3i[2] = remappedelement[2] + 1;
1185                         outelement3i[3] = remappedelement[0];
1186                         outelement3i[4] = remappedelement[2] + 1;
1187                         outelement3i[5] = remappedelement[0] + 1;
1188
1189                         outelement3i += 6;
1190                         outtriangles += 2;
1191                 }
1192         }
1193         if (outnumvertices)
1194                 *outnumvertices = outvertices;
1195         return outtriangles;
1196 }
1197
1198 void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs)
1199 {
1200         int t, tend;
1201         const int *e;
1202         const float *v[3];
1203         float normal[3];
1204         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1205                 return;
1206         tend = firsttriangle + numtris;
1207         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1208         {
1209                 // surface box entirely inside light box, no box cull
1210                 if (projectdirection)
1211                 {
1212                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1213                         {
1214                                 TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
1215                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1216                                         shadowmarklist[numshadowmark++] = t;
1217                         }
1218                 }
1219                 else
1220                 {
1221                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1222                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
1223                                         shadowmarklist[numshadowmark++] = t;
1224                 }
1225         }
1226         else
1227         {
1228                 // surface box not entirely inside light box, cull each triangle
1229                 if (projectdirection)
1230                 {
1231                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1232                         {
1233                                 v[0] = invertex3f + e[0] * 3;
1234                                 v[1] = invertex3f + e[1] * 3;
1235                                 v[2] = invertex3f + e[2] * 3;
1236                                 TriangleNormal(v[0], v[1], v[2], normal);
1237                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1238                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1239                                         shadowmarklist[numshadowmark++] = t;
1240                         }
1241                 }
1242                 else
1243                 {
1244                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1245                         {
1246                                 v[0] = invertex3f + e[0] * 3;
1247                                 v[1] = invertex3f + e[1] * 3;
1248                                 v[2] = invertex3f + e[2] * 3;
1249                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1250                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1251                                         shadowmarklist[numshadowmark++] = t;
1252                         }
1253                 }
1254         }
1255 }
1256
1257 qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
1258 {
1259 #if 1
1260         return false;
1261 #else
1262         if (r_shadow_compilingrtlight || !r_shadow_frontsidecasting.integer || !r_shadow_usezpassifpossible.integer)
1263                 return false;
1264         // check if the shadow volume intersects the near plane
1265         //
1266         // a ray between the eye and light origin may intersect the caster,
1267         // indicating that the shadow may touch the eye location, however we must
1268         // test the near plane (a polygon), not merely the eye location, so it is
1269         // easiest to enlarge the caster bounding shape slightly for this.
1270         // TODO
1271         return true;
1272 #endif
1273 }
1274
1275 void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, const vec3_t projectdirection, float projectdistance, int nummarktris, const int *marktris, vec3_t trismins, vec3_t trismaxs)
1276 {
1277         int i, tris, outverts;
1278         if (projectdistance < 0.1)
1279         {
1280                 Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
1281                 return;
1282         }
1283         if (!numverts || !nummarktris)
1284                 return;
1285         // make sure shadowelements is big enough for this volume
1286         if (maxshadowtriangles < nummarktris*8 || maxshadowvertices < numverts*2)
1287                 R_Shadow_ResizeShadowArrays(numverts, nummarktris, 2, 8);
1288
1289         if (maxvertexupdate < numverts)
1290         {
1291                 maxvertexupdate = numverts;
1292                 if (vertexupdate)
1293                         Mem_Free(vertexupdate);
1294                 if (vertexremap)
1295                         Mem_Free(vertexremap);
1296                 vertexupdate = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1297                 vertexremap = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1298                 vertexupdatenum = 0;
1299         }
1300         vertexupdatenum++;
1301         if (vertexupdatenum == 0)
1302         {
1303                 vertexupdatenum = 1;
1304                 memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
1305                 memset(vertexremap, 0, maxvertexupdate * sizeof(int));
1306         }
1307
1308         for (i = 0;i < nummarktris;i++)
1309                 shadowmark[marktris[i]] = shadowmarkcount;
1310
1311         if (r_shadow_compilingrtlight)
1312         {
1313                 // if we're compiling an rtlight, capture the mesh
1314                 //tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1315                 //Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zpass, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1316                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1317                 Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zfail, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1318         }
1319         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1320         {
1321                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1322                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1323                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1324         }
1325         else
1326         {
1327                 // decide which type of shadow to generate and set stencil mode
1328                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1329                 // generate the sides or a solid volume, depending on type
1330                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1331                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1332                 else
1333                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1334                 r_refdef.stats.lights_dynamicshadowtriangles += tris;
1335                 r_refdef.stats.lights_shadowtriangles += tris;
1336                 CHECKGLERROR
1337                 R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
1338                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1339                 {
1340                         // increment stencil if frontface is infront of depthbuffer
1341                         GL_CullFace(r_refdef.view.cullface_front);
1342                         qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
1343                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1344                         // decrement stencil if backface is infront of depthbuffer
1345                         GL_CullFace(r_refdef.view.cullface_back);
1346                         qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
1347                 }
1348                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1349                 {
1350                         // decrement stencil if backface is behind depthbuffer
1351                         GL_CullFace(r_refdef.view.cullface_front);
1352                         qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
1353                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1354                         // increment stencil if frontface is behind depthbuffer
1355                         GL_CullFace(r_refdef.view.cullface_back);
1356                         qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
1357                 }
1358                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
1359                 CHECKGLERROR
1360         }
1361 }
1362
1363 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1364 {
1365     // p1, p2, p3 are in the cubemap's local coordinate system
1366     // bias = border/(size - border)
1367         int mask = 0x3F;
1368
1369     float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1370           dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1371           dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1372         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1373         mask &= (3<<4)
1374                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1375                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1376                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1377     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1378         mask &= (3<<4)
1379             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1380             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))            
1381             | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1382
1383     dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1384     dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1385     dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1386     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1387         mask &= (3<<0)
1388             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1389             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))            
1390             | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1391     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1392         mask &= (3<<0)
1393             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1394             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1395             | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1396
1397     dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1398     dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1399     dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1400     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1401         mask &= (3<<2)
1402             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1403             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1404             | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1405     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1406         mask &= (3<<2)
1407             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1408             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1409             | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1410
1411         return mask;
1412 }
1413
1414 int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1415 {
1416         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1417         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1418         int mask = 0x3F;
1419
1420         VectorSubtract(maxs, mins, radius);
1421     VectorScale(radius, 0.5f, radius);
1422     VectorAdd(mins, radius, center);
1423     Matrix4x4_Transform(worldtolight, center, lightcenter);
1424         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1425         VectorSubtract(lightcenter, lightradius, pmin);
1426         VectorAdd(lightcenter, lightradius, pmax);
1427
1428     dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1429     dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1430     if(ap1 > bias*an1 && ap2 > bias*an2)
1431         mask &= (3<<4)
1432             | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1433             | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1434     if(an1 > bias*ap1 && an2 > bias*ap2)
1435         mask &= (3<<4)
1436             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1437             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1438
1439     dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1440     dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1441     if(ap1 > bias*an1 && ap2 > bias*an2)
1442         mask &= (3<<0)
1443             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1444             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1445     if(an1 > bias*ap1 && an2 > bias*ap2)
1446         mask &= (3<<0)
1447             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1448             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1449
1450     dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1451     dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1452     if(ap1 > bias*an1 && ap2 > bias*an2)
1453         mask &= (3<<2)
1454             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1455             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1456     if(an1 > bias*ap1 && an2 > bias*ap2)
1457         mask &= (3<<2)
1458             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1459             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1460
1461     return mask;
1462 }
1463
1464 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1465
1466 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1467 {
1468     // p is in the cubemap's local coordinate system
1469     // bias = border/(size - border)
1470     float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1471     float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1472     float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1473     int mask = 0x3F;
1474     if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1475     if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1476     if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1477     if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1478     if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1479     if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1480     return mask;
1481 }
1482
1483 int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1484 {
1485         int i;
1486         vec3_t p, n;
1487         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1488         float scale = (size - 2*border)/size, len;
1489         float bias = border / (float)(size - border), dp, dn, ap, an;
1490         // check if cone enclosing side would cross frustum plane 
1491         scale = 2 / (scale*scale + 2);
1492         for (i = 0;i < 5;i++)
1493         {
1494                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
1495                         continue;
1496                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1497                 len = scale*VectorLength2(n);
1498                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1499                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1500                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1501         }
1502         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1503         {
1504         Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1505         len = scale*VectorLength(n);
1506                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1507                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1508                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1509         }
1510         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1511         // check if frustum corners/origin cross plane sides
1512         for (i = 0;i < 5;i++)
1513         {
1514                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1515                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
1516                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1517                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1518                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
1519                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1520                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1521                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
1522                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1523                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1524         }
1525         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1526 }
1527
1528 int R_Shadow_ChooseSidesFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const matrix4x4_t *worldtolight, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs, int *totals)
1529 {
1530         int t, tend;
1531         const int *e;
1532         const float *v[3];
1533         float normal[3];
1534         vec3_t p[3];
1535         float bias;
1536         int mask, surfacemask = 0;
1537         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1538                 return 0;
1539         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1540         tend = firsttriangle + numtris;
1541         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1542         {
1543                 // surface box entirely inside light box, no box cull
1544                 if (projectdirection)
1545                 {
1546                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1547                         {
1548                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1549                                 TriangleNormal(v[0], v[1], v[2], normal);
1550                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1551                                 {
1552                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1553                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1554                                         surfacemask |= mask;
1555                                         if(totals)
1556                                         {
1557                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1558                                                 shadowsides[numshadowsides] = mask;
1559                                                 shadowsideslist[numshadowsides++] = t;
1560                                         }
1561                                 }
1562                         }
1563                 }
1564                 else
1565                 {
1566                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1567                         {
1568                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1569                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1570                                 {
1571                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1572                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1573                                         surfacemask |= mask;
1574                                         if(totals)
1575                                         {
1576                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1577                                                 shadowsides[numshadowsides] = mask;
1578                                                 shadowsideslist[numshadowsides++] = t;
1579                                         }
1580                                 }
1581                         }
1582                 }
1583         }
1584         else
1585         {
1586                 // surface box not entirely inside light box, cull each triangle
1587                 if (projectdirection)
1588                 {
1589                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1590                         {
1591                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1592                                 TriangleNormal(v[0], v[1], v[2], normal);
1593                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1594                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1595                                 {
1596                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1597                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1598                                         surfacemask |= mask;
1599                                         if(totals)
1600                                         {
1601                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1602                                                 shadowsides[numshadowsides] = mask;
1603                                                 shadowsideslist[numshadowsides++] = t;
1604                                         }
1605                                 }
1606                         }
1607                 }
1608                 else
1609                 {
1610                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1611                         {
1612                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1613                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1614                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1615                                 {
1616                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1617                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1618                                         surfacemask |= mask;
1619                                         if(totals)
1620                                         {
1621                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1622                                                 shadowsides[numshadowsides] = mask;
1623                                                 shadowsideslist[numshadowsides++] = t;
1624                                         }
1625                                 }
1626                         }
1627                 }
1628         }
1629         return surfacemask;
1630 }
1631
1632 void R_Shadow_ShadowMapFromList(int numverts, int numtris, const float *vertex3f, const int *elements, int numsidetris, const int *sidetotals, const unsigned char *sides, const int *sidetris)
1633 {
1634         int i, j, outtriangles = 0;
1635         int *outelement3i[6];
1636         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1637                 return;
1638         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1639         // make sure shadowelements is big enough for this mesh
1640         if (maxshadowtriangles < outtriangles)
1641                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1642
1643         // compute the offset and size of the separate index lists for each cubemap side
1644         outtriangles = 0;
1645         for (i = 0;i < 6;i++)
1646         {
1647                 outelement3i[i] = shadowelements + outtriangles * 3;
1648                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1649                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1650                 outtriangles += sidetotals[i];
1651         }
1652
1653         // gather up the (sparse) triangles into separate index lists for each cubemap side
1654         for (i = 0;i < numsidetris;i++)
1655         {
1656                 const int *element = elements + sidetris[i] * 3;
1657                 for (j = 0;j < 6;j++)
1658                 {
1659                         if (sides[i] & (1 << j))
1660                         {
1661                                 outelement3i[j][0] = element[0];
1662                                 outelement3i[j][1] = element[1];
1663                                 outelement3i[j][2] = element[2];
1664                                 outelement3i[j] += 3;
1665                         }
1666                 }
1667         }
1668                         
1669         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1670 }
1671
1672 static void R_Shadow_MakeTextures_MakeCorona(void)
1673 {
1674         float dx, dy;
1675         int x, y, a;
1676         unsigned char pixels[32][32][4];
1677         for (y = 0;y < 32;y++)
1678         {
1679                 dy = (y - 15.5f) * (1.0f / 16.0f);
1680                 for (x = 0;x < 32;x++)
1681                 {
1682                         dx = (x - 15.5f) * (1.0f / 16.0f);
1683                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1684                         a = bound(0, a, 255);
1685                         pixels[y][x][0] = a;
1686                         pixels[y][x][1] = a;
1687                         pixels[y][x][2] = a;
1688                         pixels[y][x][3] = 255;
1689                 }
1690         }
1691         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
1692 }
1693
1694 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1695 {
1696         float dist = sqrt(x*x+y*y+z*z);
1697         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1698         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1699         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1700 }
1701
1702 static void R_Shadow_MakeTextures(void)
1703 {
1704         int x, y, z;
1705         float intensity, dist;
1706         unsigned int *data;
1707         R_Shadow_FreeShadowMaps();
1708         R_FreeTexturePool(&r_shadow_texturepool);
1709         r_shadow_texturepool = R_AllocTexturePool();
1710         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1711         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1712         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1713         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1714         for (x = 0;x <= ATTENTABLESIZE;x++)
1715         {
1716                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1717                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1718                 r_shadow_attentable[x] = bound(0, intensity, 1);
1719         }
1720         // 1D gradient texture
1721         for (x = 0;x < ATTEN1DSIZE;x++)
1722                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1723         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1724         // 2D circle texture
1725         for (y = 0;y < ATTEN2DSIZE;y++)
1726                 for (x = 0;x < ATTEN2DSIZE;x++)
1727                         data[y*ATTEN2DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), 0);
1728         r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1729         // 3D sphere texture
1730         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1731         {
1732                 for (z = 0;z < ATTEN3DSIZE;z++)
1733                         for (y = 0;y < ATTEN3DSIZE;y++)
1734                                 for (x = 0;x < ATTEN3DSIZE;x++)
1735                                         data[(z*ATTEN3DSIZE+y)*ATTEN3DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((z + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375));
1736                 r_shadow_attenuation3dtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation3d", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL);
1737         }
1738         else
1739                 r_shadow_attenuation3dtexture = NULL;
1740         Mem_Free(data);
1741
1742         R_Shadow_MakeTextures_MakeCorona();
1743
1744         // Editor light sprites
1745         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1746         "................"
1747         ".3............3."
1748         "..5...2332...5.."
1749         "...7.3....3.7..."
1750         "....7......7...."
1751         "...3.7....7.3..."
1752         "..2...7..7...2.."
1753         "..3..........3.."
1754         "..3..........3.."
1755         "..2...7..7...2.."
1756         "...3.7....7.3..."
1757         "....7......7...."
1758         "...7.3....3.7..."
1759         "..5...2332...5.."
1760         ".3............3."
1761         "................"
1762         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1763         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1764         "................"
1765         "................"
1766         "......1111......"
1767         "....11233211...."
1768         "...1234554321..."
1769         "...1356776531..."
1770         "..124677776421.."
1771         "..135777777531.."
1772         "..135777777531.."
1773         "..124677776421.."
1774         "...1356776531..."
1775         "...1234554321..."
1776         "....11233211...."
1777         "......1111......"
1778         "................"
1779         "................"
1780         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1781         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1782         "................"
1783         "................"
1784         "......1111......"
1785         "....11233211...."
1786         "...1234554321..."
1787         "...1356226531..."
1788         "..12462..26421.."
1789         "..1352....2531.."
1790         "..1352....2531.."
1791         "..12462..26421.."
1792         "...1356226531..."
1793         "...1234554321..."
1794         "....11233211...."
1795         "......1111......"
1796         "................"
1797         "................"
1798         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1799         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1800         "................"
1801         "................"
1802         "......2772......"
1803         "....27755772...."
1804         "..277533335772.."
1805         "..753333333357.."
1806         "..777533335777.."
1807         "..735775577537.."
1808         "..733357753337.."
1809         "..733337733337.."
1810         "..753337733357.."
1811         "..277537735772.."
1812         "....27777772...."
1813         "......2772......"
1814         "................"
1815         "................"
1816         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1817         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1818         "................"
1819         "................"
1820         "......2772......"
1821         "....27722772...."
1822         "..2772....2772.."
1823         "..72........27.."
1824         "..7772....2777.."
1825         "..7.27722772.7.."
1826         "..7...2772...7.."
1827         "..7....77....7.."
1828         "..72...77...27.."
1829         "..2772.77.2772.."
1830         "....27777772...."
1831         "......2772......"
1832         "................"
1833         "................"
1834         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1835         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1836         "................"
1837         ".777752..257777."
1838         ".742........247."
1839         ".72..........27."
1840         ".7............7."
1841         ".5............5."
1842         ".2............2."
1843         "................"
1844         "................"
1845         ".2............2."
1846         ".5............5."
1847         ".7............7."
1848         ".72..........27."
1849         ".742........247."
1850         ".777752..257777."
1851         "................"
1852         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1853 }
1854
1855 void R_Shadow_ValidateCvars(void)
1856 {
1857         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
1858                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
1859         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
1860                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
1861         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
1862                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
1863 }
1864
1865 void R_Shadow_RenderMode_Begin(void)
1866 {
1867 #if 0
1868         GLint drawbuffer;
1869         GLint readbuffer;
1870 #endif
1871         R_Shadow_ValidateCvars();
1872
1873         if (!r_shadow_attenuation2dtexture
1874          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
1875          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1876          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1877                 R_Shadow_MakeTextures();
1878
1879         CHECKGLERROR
1880         R_Mesh_ColorPointer(NULL, 0, 0);
1881         R_Mesh_ResetTextureState();
1882         GL_BlendFunc(GL_ONE, GL_ZERO);
1883         GL_DepthRange(0, 1);
1884         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1885         GL_DepthTest(true);
1886         GL_DepthMask(false);
1887         GL_Color(0, 0, 0, 1);
1888         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1889
1890         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1891
1892         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
1893         {
1894                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
1895                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
1896         }
1897         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
1898         {
1899                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
1900                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
1901         }
1902         else
1903         {
1904                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
1905                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
1906         }
1907
1908         switch(vid.renderpath)
1909         {
1910         case RENDERPATH_GL20:
1911         case RENDERPATH_CGGL:
1912                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1913                 break;
1914         case RENDERPATH_GL13:
1915         case RENDERPATH_GL11:
1916                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
1917                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
1918                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
1919                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
1920                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
1921                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
1922                 else
1923                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
1924                 break;
1925         }
1926
1927         CHECKGLERROR
1928 #if 0
1929         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1930         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1931         r_shadow_drawbuffer = drawbuffer;
1932         r_shadow_readbuffer = readbuffer;
1933 #endif
1934         r_shadow_cullface_front = r_refdef.view.cullface_front;
1935         r_shadow_cullface_back = r_refdef.view.cullface_back;
1936 }
1937
1938 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
1939 {
1940         rsurface.rtlight = rtlight;
1941 }
1942
1943 void R_Shadow_RenderMode_Reset(void)
1944 {
1945         CHECKGLERROR
1946         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE)
1947         {
1948                 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1949         }
1950         if (vid.support.ext_framebuffer_object)
1951         {
1952                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
1953         }
1954 #if 0
1955         qglDrawBuffer(r_shadow_drawbuffer);CHECKGLERROR
1956         qglReadBuffer(r_shadow_readbuffer);CHECKGLERROR
1957 #endif
1958         R_SetViewport(&r_refdef.view.viewport);
1959         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
1960         R_Mesh_ColorPointer(NULL, 0, 0);
1961         R_Mesh_ResetTextureState();
1962         GL_DepthRange(0, 1);
1963         GL_DepthTest(true);
1964         GL_DepthMask(false);
1965         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1966         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1967         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1968         qglStencilMask(255);CHECKGLERROR
1969         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1970         qglStencilFunc(GL_ALWAYS, 128, 255);CHECKGLERROR
1971         r_refdef.view.cullface_front = r_shadow_cullface_front;
1972         r_refdef.view.cullface_back = r_shadow_cullface_back;
1973         GL_CullFace(r_refdef.view.cullface_back);
1974         GL_Color(1, 1, 1, 1);
1975         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
1976         GL_BlendFunc(GL_ONE, GL_ZERO);
1977         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
1978         r_shadow_usingshadowmaprect = false;
1979         r_shadow_usingshadowmapcube = false;
1980         r_shadow_usingshadowmap2d = false;
1981         CHECKGLERROR
1982 }
1983
1984 void R_Shadow_ClearStencil(void)
1985 {
1986         CHECKGLERROR
1987         GL_Clear(GL_STENCIL_BUFFER_BIT);
1988         r_refdef.stats.lights_clears++;
1989 }
1990
1991 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
1992 {
1993         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
1994         if (r_shadow_rendermode == mode)
1995                 return;
1996         CHECKGLERROR
1997         R_Shadow_RenderMode_Reset();
1998         GL_ColorMask(0, 0, 0, 0);
1999         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2000         R_SetupShader_DepthOrShadow();
2001         qglDepthFunc(GL_LESS);CHECKGLERROR
2002         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2003         r_shadow_rendermode = mode;
2004         switch(mode)
2005         {
2006         default:
2007                 break;
2008         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
2009                 GL_CullFace(GL_NONE);
2010                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
2011                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
2012                 break;
2013         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
2014                 GL_CullFace(GL_NONE);
2015                 qglStencilOpSeparate(r_refdef.view.cullface_front, GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
2016                 qglStencilOpSeparate(r_refdef.view.cullface_back, GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
2017                 break;
2018         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
2019                 GL_CullFace(GL_NONE);
2020                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2021                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
2022                 qglStencilMask(255);CHECKGLERROR
2023                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
2024                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
2025                 qglStencilMask(255);CHECKGLERROR
2026                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
2027                 break;
2028         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2029                 GL_CullFace(GL_NONE);
2030                 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2031                 qglActiveStencilFaceEXT(r_refdef.view.cullface_front);CHECKGLERROR
2032                 qglStencilMask(255);CHECKGLERROR
2033                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
2034                 qglActiveStencilFaceEXT(r_refdef.view.cullface_back);CHECKGLERROR
2035                 qglStencilMask(255);CHECKGLERROR
2036                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
2037                 break;
2038         }
2039 }
2040
2041 static void R_Shadow_MakeVSDCT(void)
2042 {
2043         // maps to a 2x3 texture rectangle with normalized coordinates
2044         // +-
2045         // XX
2046         // YY
2047         // ZZ
2048         // stores abs(dir.xy), offset.xy/2.5
2049         unsigned char data[4*6] =
2050         {
2051                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2052                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2053                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2054                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2055                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2056                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2057         };
2058         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, NULL);
2059 }
2060
2061 static void R_Shadow_MakeShadowMap(int side, int size)
2062 {
2063         int status;
2064         switch (r_shadow_shadowmode)
2065         {
2066         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2067                 if (r_shadow_shadowmap2dtexture) return;
2068                 r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2069                 qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
2070                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
2071                 qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
2072                 break;
2073         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2074                 if (r_shadow_shadowmaprectangletexture) return;
2075                 r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", size*2, size*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2076                 qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
2077                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
2078                 qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
2079                 break;
2080         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2081                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) return;
2082                 r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2083                 qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2084                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
2085                 qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2086                 break;
2087         default:
2088                 return;
2089         }
2090         // render depth into the fbo, do not render color at all
2091         qglDrawBuffer(GL_NONE);CHECKGLERROR
2092         qglReadBuffer(GL_NONE);CHECKGLERROR
2093         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2094         if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2095         {
2096                 Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2097                 Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2098                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
2099         }
2100 }
2101         
2102 void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
2103 {
2104         float nearclip, farclip, bias;
2105         r_viewport_t viewport;
2106         int flipped;
2107         GLuint fbo = 0;
2108         CHECKGLERROR
2109         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2110         farclip = 1.0f;
2111         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2112         r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2113         r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2114         r_shadow_shadowmapside = side;
2115         r_shadow_shadowmapsize = size;
2116         switch (r_shadow_shadowmode)
2117         {
2118         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2119                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2120                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2121                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2122                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
2123
2124                 // complex unrolled cube approach (more flexible)
2125                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2126                         R_Shadow_MakeVSDCT();
2127                 if (!r_shadow_shadowmap2dtexture)
2128                         R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
2129                 CHECKGLERROR
2130                 if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
2131                 r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
2132                 r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
2133                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2134                 break;
2135         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2136                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2137                 r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2138                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2139                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
2140
2141                 // complex unrolled cube approach (more flexible)
2142                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2143                         R_Shadow_MakeVSDCT();
2144                 if (!r_shadow_shadowmaprectangletexture)
2145                         R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
2146                 CHECKGLERROR
2147                 if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
2148                 r_shadow_shadowmap_texturescale[0] = 1.0f;
2149                 r_shadow_shadowmap_texturescale[1] = 1.0f;
2150                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
2151                 break;
2152         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2153                 r_shadow_shadowmap_parameters[0] = 1.0f;
2154                 r_shadow_shadowmap_parameters[1] = 1.0f;
2155                 R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
2156                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
2157
2158                 // simple cube approach
2159                 if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
2160                         R_Shadow_MakeShadowMap(side, size);
2161                 CHECKGLERROR
2162                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
2163                 r_shadow_shadowmap_texturescale[0] = 0.0f;
2164                 r_shadow_shadowmap_texturescale[1] = 0.0f;
2165                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
2166                 break;
2167         default:
2168                 break;
2169         }
2170
2171         R_Shadow_RenderMode_Reset();
2172         if (fbo)
2173         {
2174                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
2175                 R_SetupShader_DepthOrShadow();
2176         }
2177         else
2178         {
2179                 R_SetupShader_ShowDepth();
2180                 qglClearColor(1,1,1,1);CHECKGLERROR
2181         }
2182         CHECKGLERROR
2183         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2184         GL_DepthMask(true);
2185         GL_DepthTest(true);
2186         qglClearDepth(1);
2187         CHECKGLERROR
2188
2189 init_done:
2190         R_SetViewport(&viewport);
2191         switch (r_shadow_rendermode)
2192         {
2193         case R_SHADOW_RENDERMODE_SHADOWMAP2D:
2194         case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE:
2195                 flipped = (side & 1) ^ (side >> 2);
2196                 r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2197                 r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2198                 GL_CullFace(r_refdef.view.cullface_back);
2199                 if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
2200                 {
2201                         // get tightest scissor rectangle that encloses all viewports in the clear mask
2202                         int x1 = clear & 0x15 ? 0 : size;
2203                         int x2 = clear & 0x2A ? 2 * size : size;
2204                         int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
2205                         int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
2206                         GL_Scissor(x1, y1, x2 - x1, y2 - y1);
2207                         GL_Clear(GL_DEPTH_BUFFER_BIT);
2208                 }
2209                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2210                 break;
2211         case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
2212                 qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2213                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2214                 if (clear)
2215                         GL_Clear(GL_DEPTH_BUFFER_BIT);
2216                 break;
2217         default:
2218                 break;
2219         }
2220         CHECKGLERROR
2221 }
2222
2223 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
2224 {
2225         if (transparent)
2226         {
2227                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2228                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2229                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2230                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2231         }
2232         CHECKGLERROR
2233         R_Shadow_RenderMode_Reset();
2234         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2235         if (!transparent)
2236         {
2237                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2238         }
2239         if (stenciltest)
2240         {
2241                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2242                 // only draw light where this geometry was already rendered AND the
2243                 // stencil is 128 (values other than this mean shadow)
2244                 qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
2245         }
2246         r_shadow_rendermode = r_shadow_lightingrendermode;
2247         // do global setup needed for the chosen lighting mode
2248         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2249         {
2250                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2251                 CHECKGLERROR
2252         }
2253         if (shadowmapping)
2254         {
2255                 switch (r_shadow_shadowmode)
2256                 {
2257                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2258                         r_shadow_usingshadowmap2d = true;
2259                         break;
2260                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2261                         r_shadow_usingshadowmaprect = true;
2262                         break;
2263                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2264                         r_shadow_usingshadowmapcube = true;
2265                         break;
2266                 default:
2267                         break;
2268                 }
2269         }
2270         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
2271         CHECKGLERROR
2272 }
2273
2274 static const unsigned short bboxelements[36] =
2275 {
2276         5, 1, 3, 5, 3, 7,
2277         6, 2, 0, 6, 0, 4,
2278         7, 3, 2, 7, 2, 6,
2279         4, 0, 1, 4, 1, 5,
2280         4, 5, 7, 4, 7, 6,
2281         1, 0, 2, 1, 2, 3,
2282 };
2283
2284 static const float bboxpoints[8][3] =
2285 {
2286         {-1,-1,-1},
2287         { 1,-1,-1},
2288         {-1, 1,-1},
2289         { 1, 1,-1},
2290         {-1,-1, 1},
2291         { 1,-1, 1},
2292         {-1, 1, 1},
2293         { 1, 1, 1},
2294 };
2295
2296 void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadowmapping)
2297 {
2298         int i;
2299         float vertex3f[8*3];
2300         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
2301         CHECKGLERROR
2302         R_Shadow_RenderMode_Reset();
2303         r_shadow_rendermode = r_shadow_lightingrendermode;
2304         // do global setup needed for the chosen lighting mode
2305         {
2306                 R_EntityMatrix(&identitymatrix);
2307                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2308                 if (stenciltest)
2309                 {
2310                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2311                         // only draw light where this geometry was already rendered AND the
2312                         // stencil is 128 (values other than this mean shadow)
2313                         qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
2314                 }
2315                 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
2316                 if (shadowmapping)
2317                 {
2318                         if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
2319                                 r_shadow_usingshadowmap2d = true;
2320                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
2321                                 r_shadow_usingshadowmaprect = true;
2322                         else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
2323                                 r_shadow_usingshadowmapcube = true;
2324                 }
2325
2326                 // render the lighting
2327                 R_SetupShader_DeferredLight(rsurface.rtlight);
2328                 for (i = 0;i < 8;i++)
2329                         Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
2330                 CHECKGLERROR
2331                 R_Mesh_VertexPointer(vertex3f, 0, 0);
2332                 R_Mesh_ColorPointer(NULL, 0, 0);
2333                 GL_ColorMask(1,1,1,1);
2334                 GL_DepthMask(false);
2335                 GL_DepthRange(0, 1);
2336                 GL_PolygonOffset(0, 0);
2337                 GL_DepthTest(true);
2338                 qglDepthFunc(GL_GREATER);CHECKGLERROR
2339                 GL_CullFace(r_refdef.view.cullface_back);
2340                 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
2341         }
2342 }
2343
2344 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
2345 {
2346         CHECKGLERROR
2347         R_Shadow_RenderMode_Reset();
2348         GL_BlendFunc(GL_ONE, GL_ONE);
2349         GL_DepthRange(0, 1);
2350         GL_DepthTest(r_showshadowvolumes.integer < 2);
2351         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
2352         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2353         GL_CullFace(GL_NONE);
2354         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
2355 }
2356
2357 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
2358 {
2359         CHECKGLERROR
2360         R_Shadow_RenderMode_Reset();
2361         GL_BlendFunc(GL_ONE, GL_ONE);
2362         GL_DepthRange(0, 1);
2363         GL_DepthTest(r_showlighting.integer < 2);
2364         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2365         if (!transparent)
2366         {
2367                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2368         }
2369         if (stenciltest)
2370         {
2371                 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2372                 qglStencilFunc(GL_EQUAL, 128, 255);CHECKGLERROR
2373         }
2374         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2375 }
2376
2377 void R_Shadow_RenderMode_End(void)
2378 {
2379         CHECKGLERROR
2380         R_Shadow_RenderMode_Reset();
2381         R_Shadow_RenderMode_ActiveLight(NULL);
2382         GL_DepthMask(true);
2383         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2384         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2385 }
2386
2387 int bboxedges[12][2] =
2388 {
2389         // top
2390         {0, 1}, // +X
2391         {0, 2}, // +Y
2392         {1, 3}, // Y, +X
2393         {2, 3}, // X, +Y
2394         // bottom
2395         {4, 5}, // +X
2396         {4, 6}, // +Y
2397         {5, 7}, // Y, +X
2398         {6, 7}, // X, +Y
2399         // verticals
2400         {0, 4}, // +Z
2401         {1, 5}, // X, +Z
2402         {2, 6}, // Y, +Z
2403         {3, 7}, // XY, +Z
2404 };
2405
2406 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2407 {
2408         int i, ix1, iy1, ix2, iy2;
2409         float x1, y1, x2, y2;
2410         vec4_t v, v2;
2411         float vertex[20][3];
2412         int j, k;
2413         vec4_t plane4f;
2414         int numvertices;
2415         float corner[8][4];
2416         float dist[8];
2417         int sign[8];
2418         float f;
2419
2420         r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2421         r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2422         r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2423         r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2424
2425         if (!r_shadow_scissor.integer)
2426                 return false;
2427
2428         // if view is inside the light box, just say yes it's visible
2429         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
2430                 return false;
2431
2432         x1 = y1 = x2 = y2 = 0;
2433
2434         // transform all corners that are infront of the nearclip plane
2435         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
2436         plane4f[3] = r_refdef.view.frustum[4].dist;
2437         numvertices = 0;
2438         for (i = 0;i < 8;i++)
2439         {
2440                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
2441                 dist[i] = DotProduct4(corner[i], plane4f);
2442                 sign[i] = dist[i] > 0;
2443                 if (!sign[i])
2444                 {
2445                         VectorCopy(corner[i], vertex[numvertices]);
2446                         numvertices++;
2447                 }
2448         }
2449         // if some points are behind the nearclip, add clipped edge points to make
2450         // sure that the scissor boundary is complete
2451         if (numvertices > 0 && numvertices < 8)
2452         {
2453                 // add clipped edge points
2454                 for (i = 0;i < 12;i++)
2455                 {
2456                         j = bboxedges[i][0];
2457                         k = bboxedges[i][1];
2458                         if (sign[j] != sign[k])
2459                         {
2460                                 f = dist[j] / (dist[j] - dist[k]);
2461                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
2462                                 numvertices++;
2463                         }
2464                 }
2465         }
2466
2467         // if we have no points to check, the light is behind the view plane
2468         if (!numvertices)
2469                 return true;
2470
2471         // if we have some points to transform, check what screen area is covered
2472         x1 = y1 = x2 = y2 = 0;
2473         v[3] = 1.0f;
2474         //Con_Printf("%i vertices to transform...\n", numvertices);
2475         for (i = 0;i < numvertices;i++)
2476         {
2477                 VectorCopy(vertex[i], v);
2478                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
2479                 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
2480                 if (i)
2481                 {
2482                         if (x1 > v2[0]) x1 = v2[0];
2483                         if (x2 < v2[0]) x2 = v2[0];
2484                         if (y1 > v2[1]) y1 = v2[1];
2485                         if (y2 < v2[1]) y2 = v2[1];
2486                 }
2487                 else
2488                 {
2489                         x1 = x2 = v2[0];
2490                         y1 = y2 = v2[1];
2491                 }
2492         }
2493
2494         // now convert the scissor rectangle to integer screen coordinates
2495         ix1 = (int)(x1 - 1.0f);
2496         iy1 = vid.height - (int)(y2 - 1.0f);
2497         ix2 = (int)(x2 + 1.0f);
2498         iy2 = vid.height - (int)(y1 + 1.0f);
2499         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
2500
2501         // clamp it to the screen
2502         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
2503         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
2504         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
2505         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
2506
2507         // if it is inside out, it's not visible
2508         if (ix2 <= ix1 || iy2 <= iy1)
2509                 return true;
2510
2511         // the light area is visible, set up the scissor rectangle
2512         r_shadow_lightscissor[0] = ix1;
2513         r_shadow_lightscissor[1] = iy1;
2514         r_shadow_lightscissor[2] = ix2 - ix1;
2515         r_shadow_lightscissor[3] = iy2 - iy1;
2516
2517         r_refdef.stats.lights_scissored++;
2518         return false;
2519 }
2520
2521 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
2522 {
2523         const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
2524         const float *normal3f = rsurface.normal3f + 3 * firstvertex;
2525         float *color4f = rsurface.array_color4f + 4 * firstvertex;
2526         float dist, dot, distintensity, shadeintensity, v[3], n[3];
2527         switch (r_shadow_rendermode)
2528         {
2529         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2530         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2531                 if (VectorLength2(diffusecolor) > 0)
2532                 {
2533                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2534                         {
2535                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2536                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2537                                 if ((dot = DotProduct(n, v)) < 0)
2538                                 {
2539                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2540                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
2541                                 }
2542                                 else
2543                                         VectorCopy(ambientcolor, color4f);
2544                                 if (r_refdef.fogenabled)
2545                                 {
2546                                         float f;
2547                                         f = RSurf_FogVertex(vertex3f);
2548                                         VectorScale(color4f, f, color4f);
2549                                 }
2550                                 color4f[3] = 1;
2551                         }
2552                 }
2553                 else
2554                 {
2555                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2556                         {
2557                                 VectorCopy(ambientcolor, color4f);
2558                                 if (r_refdef.fogenabled)
2559                                 {
2560                                         float f;
2561                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2562                                         f = RSurf_FogVertex(vertex3f);
2563                                         VectorScale(color4f, f, color4f);
2564                                 }
2565                                 color4f[3] = 1;
2566                         }
2567                 }
2568                 break;
2569         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2570                 if (VectorLength2(diffusecolor) > 0)
2571                 {
2572                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2573                         {
2574                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2575                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2576                                 {
2577                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2578                                         if ((dot = DotProduct(n, v)) < 0)
2579                                         {
2580                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2581                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2582                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2583                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2584                                         }
2585                                         else
2586                                         {
2587                                                 color4f[0] = ambientcolor[0] * distintensity;
2588                                                 color4f[1] = ambientcolor[1] * distintensity;
2589                                                 color4f[2] = ambientcolor[2] * distintensity;
2590                                         }
2591                                         if (r_refdef.fogenabled)
2592                                         {
2593                                                 float f;
2594                                                 f = RSurf_FogVertex(vertex3f);
2595                                                 VectorScale(color4f, f, color4f);
2596                                         }
2597                                 }
2598                                 else
2599                                         VectorClear(color4f);
2600                                 color4f[3] = 1;
2601                         }
2602                 }
2603                 else
2604                 {
2605                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2606                         {
2607                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2608                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2609                                 {
2610                                         color4f[0] = ambientcolor[0] * distintensity;
2611                                         color4f[1] = ambientcolor[1] * distintensity;
2612                                         color4f[2] = ambientcolor[2] * distintensity;
2613                                         if (r_refdef.fogenabled)
2614                                         {
2615                                                 float f;
2616                                                 f = RSurf_FogVertex(vertex3f);
2617                                                 VectorScale(color4f, f, color4f);
2618                                         }
2619                                 }
2620                                 else
2621                                         VectorClear(color4f);
2622                                 color4f[3] = 1;
2623                         }
2624                 }
2625                 break;
2626         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2627                 if (VectorLength2(diffusecolor) > 0)
2628                 {
2629                         for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4)
2630                         {
2631                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2632                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2633                                 {
2634                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2635                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2636                                         if ((dot = DotProduct(n, v)) < 0)
2637                                         {
2638                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2639                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2640                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2641                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2642                                         }
2643                                         else
2644                                         {
2645                                                 color4f[0] = ambientcolor[0] * distintensity;
2646                                                 color4f[1] = ambientcolor[1] * distintensity;
2647                                                 color4f[2] = ambientcolor[2] * distintensity;
2648                                         }
2649                                         if (r_refdef.fogenabled)
2650                                         {
2651                                                 float f;
2652                                                 f = RSurf_FogVertex(vertex3f);
2653                                                 VectorScale(color4f, f, color4f);
2654                                         }
2655                                 }
2656                                 else
2657                                         VectorClear(color4f);
2658                                 color4f[3] = 1;
2659                         }
2660                 }
2661                 else
2662                 {
2663                         for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4)
2664                         {
2665                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2666                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2667                                 {
2668                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2669                                         color4f[0] = ambientcolor[0] * distintensity;
2670                                         color4f[1] = ambientcolor[1] * distintensity;
2671                                         color4f[2] = ambientcolor[2] * distintensity;
2672                                         if (r_refdef.fogenabled)
2673                                         {
2674                                                 float f;
2675                                                 f = RSurf_FogVertex(vertex3f);
2676                                                 VectorScale(color4f, f, color4f);
2677                                         }
2678                                 }
2679                                 else
2680                                         VectorClear(color4f);
2681                                 color4f[3] = 1;
2682                         }
2683                 }
2684                 break;
2685         default:
2686                 break;
2687         }
2688 }
2689
2690 static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
2691 {
2692         // used to display how many times a surface is lit for level design purposes
2693         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2694 }
2695
2696 static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
2697 {
2698         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2699         R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT);
2700         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2701         {
2702                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2703         }
2704         R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2705         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2706         {
2707                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2708         }
2709 }
2710
2711 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
2712 {
2713         int renders;
2714         int i;
2715         int stop;
2716         int newfirstvertex;
2717         int newlastvertex;
2718         int newnumtriangles;
2719         int *newe;
2720         const int *e;
2721         float *c;
2722         int maxtriangles = 4096;
2723         static int newelements[4096*3];
2724         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2);
2725         for (renders = 0;renders < 4;renders++)
2726         {
2727                 stop = true;
2728                 newfirstvertex = 0;
2729                 newlastvertex = 0;
2730                 newnumtriangles = 0;
2731                 newe = newelements;
2732                 // due to low fillrate on the cards this vertex lighting path is
2733                 // designed for, we manually cull all triangles that do not
2734                 // contain a lit vertex
2735                 // this builds batches of triangles from multiple surfaces and
2736                 // renders them at once
2737                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
2738                 {
2739                         if (VectorLength2(rsurface.array_color4f + e[0] * 4) + VectorLength2(rsurface.array_color4f + e[1] * 4) + VectorLength2(rsurface.array_color4f + e[2] * 4) >= 0.01)
2740                         {
2741                                 if (newnumtriangles)
2742                                 {
2743                                         newfirstvertex = min(newfirstvertex, e[0]);
2744                                         newlastvertex  = max(newlastvertex, e[0]);
2745                                 }
2746                                 else
2747                                 {
2748                                         newfirstvertex = e[0];
2749                                         newlastvertex = e[0];
2750                                 }
2751                                 newfirstvertex = min(newfirstvertex, e[1]);
2752                                 newlastvertex  = max(newlastvertex, e[1]);
2753                                 newfirstvertex = min(newfirstvertex, e[2]);
2754                                 newlastvertex  = max(newlastvertex, e[2]);
2755                                 newe[0] = e[0];
2756                                 newe[1] = e[1];
2757                                 newe[2] = e[2];
2758                                 newnumtriangles++;
2759                                 newe += 3;
2760                                 if (newnumtriangles >= maxtriangles)
2761                                 {
2762                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2763                                         newnumtriangles = 0;
2764                                         newe = newelements;
2765                                         stop = false;
2766                                 }
2767                         }
2768                 }
2769                 if (newnumtriangles >= 1)
2770                 {
2771                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0);
2772                         stop = false;
2773                 }
2774                 // if we couldn't find any lit triangles, exit early
2775                 if (stop)
2776                         break;
2777                 // now reduce the intensity for the next overbright pass
2778                 // we have to clamp to 0 here incase the drivers have improper
2779                 // handling of negative colors
2780                 // (some old drivers even have improper handling of >1 color)
2781                 stop = true;
2782                 for (i = 0, c = rsurface.array_color4f + 4 * firstvertex;i < numvertices;i++, c += 4)
2783                 {
2784                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
2785                         {
2786                                 c[0] = max(0, c[0] - 1);
2787                                 c[1] = max(0, c[1] - 1);
2788                                 c[2] = max(0, c[2] - 1);
2789                                 stop = false;
2790                         }
2791                         else
2792                                 VectorClear(c);
2793                 }
2794                 // another check...
2795                 if (stop)
2796                         break;
2797         }
2798 }
2799
2800 static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, const vec3_t lightcolor, float ambientscale, float diffusescale)
2801 {
2802         // OpenGL 1.1 path (anything)
2803         float ambientcolorbase[3], diffusecolorbase[3];
2804         float ambientcolorpants[3], diffusecolorpants[3];
2805         float ambientcolorshirt[3], diffusecolorshirt[3];
2806         const float *surfacecolor = rsurface.texture->dlightcolor;
2807         const float *surfacepants = rsurface.colormap_pantscolor;
2808         const float *surfaceshirt = rsurface.colormap_shirtcolor;
2809         rtexture_t *basetexture = rsurface.texture->basetexture;
2810         rtexture_t *pantstexture = rsurface.texture->pantstexture;
2811         rtexture_t *shirttexture = rsurface.texture->shirttexture;
2812         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
2813         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
2814         ambientscale *= 2 * r_refdef.view.colorscale;
2815         diffusescale *= 2 * r_refdef.view.colorscale;
2816         ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
2817         diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
2818         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
2819         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
2820         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
2821         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
2822         R_Mesh_TexBind(0, basetexture);
2823         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
2824         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2825         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
2826         switch(r_shadow_rendermode)
2827         {
2828         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2829                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
2830                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2831                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2832                 R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2833                 break;
2834         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2835                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
2836                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
2837                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
2838                 R_Mesh_TexCoordPointer(2, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2839                 // fall through
2840         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2841                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
2842                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2843                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2844                 R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
2845                 break;
2846         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2847                 break;
2848         default:
2849                 break;
2850         }
2851         //R_Mesh_TexBind(0, basetexture);
2852         R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase);
2853         if (dopants)
2854         {
2855                 R_Mesh_TexBind(0, pantstexture);
2856                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants);
2857         }
2858         if (doshirt)
2859         {
2860                 R_Mesh_TexBind(0, shirttexture);
2861                 R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt);
2862         }
2863 }
2864
2865 extern cvar_t gl_lightmaps;
2866 void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
2867 {
2868         float ambientscale, diffusescale, specularscale;
2869         qboolean negated;
2870         float lightcolor[3];
2871         VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
2872         ambientscale = rsurface.rtlight->ambientscale;
2873         diffusescale = rsurface.rtlight->diffusescale;
2874         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
2875         if (!r_shadow_usenormalmap.integer)
2876         {
2877                 ambientscale += 1.0f * diffusescale;
2878                 diffusescale = 0;
2879                 specularscale = 0;
2880         }
2881         if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
2882                 return;
2883         negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
2884         if(negated)
2885         {
2886                 VectorNegate(lightcolor, lightcolor);
2887                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2888         }
2889         RSurf_SetupDepthAndCulling();
2890         switch (r_shadow_rendermode)
2891         {
2892         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
2893                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
2894                 R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject);
2895                 break;
2896         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
2897                 R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolor, ambientscale, diffusescale, specularscale);
2898                 break;
2899         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2900         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2901         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2902         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2903                 R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolor, ambientscale, diffusescale);
2904                 break;
2905         default:
2906                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2907                 break;
2908         }
2909         if(negated)
2910                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2911 }
2912
2913 void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
2914 {
2915         matrix4x4_t tempmatrix = *matrix;
2916         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
2917
2918         // if this light has been compiled before, free the associated data
2919         R_RTLight_Uncompile(rtlight);
2920
2921         // clear it completely to avoid any lingering data
2922         memset(rtlight, 0, sizeof(*rtlight));
2923
2924         // copy the properties
2925         rtlight->matrix_lighttoworld = tempmatrix;
2926         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
2927         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
2928         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
2929         VectorCopy(color, rtlight->color);
2930         rtlight->cubemapname[0] = 0;
2931         if (cubemapname && cubemapname[0])
2932                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
2933         rtlight->shadow = shadow;
2934         rtlight->corona = corona;
2935         rtlight->style = style;
2936         rtlight->isstatic = isstatic;
2937         rtlight->coronasizescale = coronasizescale;
2938         rtlight->ambientscale = ambientscale;
2939         rtlight->diffusescale = diffusescale;
2940         rtlight->specularscale = specularscale;
2941         rtlight->flags = flags;
2942
2943         // compute derived data
2944         //rtlight->cullradius = rtlight->radius;
2945         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
2946         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2947         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2948         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2949         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2950         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2951         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2952 }
2953
2954 // compiles rtlight geometry
2955 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
2956 void R_RTLight_Compile(rtlight_t *rtlight)
2957 {
2958         int i;
2959         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
2960         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
2961         entity_render_t *ent = r_refdef.scene.worldentity;
2962         dp_model_t *model = r_refdef.scene.worldmodel;
2963         unsigned char *data;
2964         shadowmesh_t *mesh;
2965
2966         // compile the light
2967         rtlight->compiled = true;
2968         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
2969         rtlight->static_numleafs = 0;
2970         rtlight->static_numleafpvsbytes = 0;
2971         rtlight->static_leaflist = NULL;
2972         rtlight->static_leafpvs = NULL;
2973         rtlight->static_numsurfaces = 0;
2974         rtlight->static_surfacelist = NULL;
2975         rtlight->static_shadowmap_receivers = 0x3F;
2976         rtlight->static_shadowmap_casters = 0x3F;
2977         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
2978         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
2979         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
2980         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
2981         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
2982         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
2983
2984         if (model && model->GetLightInfo)
2985         {
2986                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
2987                 r_shadow_compilingrtlight = rtlight;
2988                 model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs, 0, NULL);
2989                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
2990                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
2991                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
2992                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
2993                 rtlight->static_numsurfaces = numsurfaces;
2994                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
2995                 rtlight->static_numleafs = numleafs;
2996                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
2997                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
2998                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
2999                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
3000                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
3001                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
3002                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
3003                 if (rtlight->static_numsurfaces)
3004                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
3005                 if (rtlight->static_numleafs)
3006                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3007                 if (rtlight->static_numleafpvsbytes)
3008                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
3009                 if (rtlight->static_numshadowtrispvsbytes)
3010                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
3011                 if (rtlight->static_numlighttrispvsbytes)
3012                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
3013                 switch (rtlight->shadowmode)
3014                 {
3015                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
3016                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
3017                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
3018                         if (model->CompileShadowMap && rtlight->shadow)
3019                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3020                         break;
3021                 default:
3022                         if (model->CompileShadowVolume && rtlight->shadow)
3023                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3024                         break;
3025                 }
3026                 // now we're done compiling the rtlight
3027                 r_shadow_compilingrtlight = NULL;
3028         }
3029
3030
3031         // use smallest available cullradius - box radius or light radius
3032         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
3033         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
3034
3035         shadowzpasstris = 0;
3036         if (rtlight->static_meshchain_shadow_zpass)
3037                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
3038                         shadowzpasstris += mesh->numtriangles;
3039
3040         shadowzfailtris = 0;
3041         if (rtlight->static_meshchain_shadow_zfail)
3042                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
3043                         shadowzfailtris += mesh->numtriangles;
3044
3045         lighttris = 0;
3046         if (rtlight->static_numlighttrispvsbytes)
3047                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
3048                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
3049                                 lighttris++;
3050
3051         shadowtris = 0;
3052         if (rtlight->static_numlighttrispvsbytes)
3053                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
3054                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
3055                                 shadowtris++;
3056
3057         if (developer_extra.integer)
3058                 Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
3059 }
3060
3061 void R_RTLight_Uncompile(rtlight_t *rtlight)
3062 {
3063         if (rtlight->compiled)
3064         {
3065                 if (rtlight->static_meshchain_shadow_zpass)
3066                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
3067                 rtlight->static_meshchain_shadow_zpass = NULL;
3068                 if (rtlight->static_meshchain_shadow_zfail)
3069                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
3070                 rtlight->static_meshchain_shadow_zfail = NULL;
3071                 if (rtlight->static_meshchain_shadow_shadowmap)
3072                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
3073                 rtlight->static_meshchain_shadow_shadowmap = NULL;
3074                 // these allocations are grouped
3075                 if (rtlight->static_surfacelist)
3076                         Mem_Free(rtlight->static_surfacelist);
3077                 rtlight->static_numleafs = 0;
3078                 rtlight->static_numleafpvsbytes = 0;
3079                 rtlight->static_leaflist = NULL;
3080                 rtlight->static_leafpvs = NULL;
3081                 rtlight->static_numsurfaces = 0;
3082                 rtlight->static_surfacelist = NULL;
3083                 rtlight->static_numshadowtrispvsbytes = 0;
3084                 rtlight->static_shadowtrispvs = NULL;
3085                 rtlight->static_numlighttrispvsbytes = 0;
3086                 rtlight->static_lighttrispvs = NULL;
3087                 rtlight->compiled = false;
3088         }
3089 }
3090
3091 void R_Shadow_UncompileWorldLights(void)
3092 {
3093         size_t lightindex;
3094         dlight_t *light;
3095         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3096         for (lightindex = 0;lightindex < range;lightindex++)
3097         {
3098                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3099                 if (!light)
3100                         continue;
3101                 R_RTLight_Uncompile(&light->rtlight);
3102         }
3103 }
3104
3105 void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
3106 {
3107         int i, j;
3108         mplane_t plane;
3109         // reset the count of frustum planes
3110         // see rtlight->cached_frustumplanes definition for how much this array
3111         // can hold
3112         rtlight->cached_numfrustumplanes = 0;
3113
3114         // haven't implemented a culling path for ortho rendering
3115         if (!r_refdef.view.useperspective)
3116         {
3117                 // check if the light is on screen and copy the 4 planes if it is
3118                 for (i = 0;i < 4;i++)
3119                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3120                                 break;
3121                 if (i == 4)
3122                         for (i = 0;i < 4;i++)
3123                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3124                 return;
3125         }
3126
3127 #if 1
3128         // generate a deformed frustum that includes the light origin, this is
3129         // used to cull shadow casting surfaces that can not possibly cast a
3130         // shadow onto the visible light-receiving surfaces, which can be a
3131         // performance gain
3132         //
3133         // if the light origin is onscreen the result will be 4 planes exactly
3134         // if the light origin is offscreen on only one axis the result will
3135         // be exactly 5 planes (split-side case)
3136         // if the light origin is offscreen on two axes the result will be
3137         // exactly 4 planes (stretched corner case)
3138         for (i = 0;i < 4;i++)
3139         {
3140                 // quickly reject standard frustum planes that put the light
3141                 // origin outside the frustum
3142                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3143                         continue;
3144                 // copy the plane
3145                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3146         }
3147         // if all the standard frustum planes were accepted, the light is onscreen
3148         // otherwise we need to generate some more planes below...
3149         if (rtlight->cached_numfrustumplanes < 4)
3150         {
3151                 // at least one of the stock frustum planes failed, so we need to
3152                 // create one or two custom planes to enclose the light origin
3153                 for (i = 0;i < 4;i++)
3154                 {
3155                         // create a plane using the view origin and light origin, and a
3156                         // single point from the frustum corner set
3157                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
3158                         VectorNormalize(plane.normal);
3159                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
3160                         // see if this plane is backwards and flip it if so
3161                         for (j = 0;j < 4;j++)
3162                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3163                                         break;
3164                         if (j < 4)
3165                         {
3166                                 VectorNegate(plane.normal, plane.normal);
3167                                 plane.dist *= -1;
3168                                 // flipped plane, test again to see if it is now valid
3169                                 for (j = 0;j < 4;j++)
3170                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3171                                                 break;
3172                                 // if the plane is still not valid, then it is dividing the
3173                                 // frustum and has to be rejected
3174                                 if (j < 4)
3175                                         continue;
3176                         }
3177                         // we have created a valid plane, compute extra info
3178                         PlaneClassify(&plane);
3179                         // copy the plane
3180                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3181 #if 1
3182                         // if we've found 5 frustum planes then we have constructed a
3183                         // proper split-side case and do not need to keep searching for
3184                         // planes to enclose the light origin
3185                         if (rtlight->cached_numfrustumplanes == 5)
3186                                 break;
3187 #endif
3188                 }
3189         }
3190 #endif
3191
3192 #if 0
3193         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
3194         {
3195                 plane = rtlight->cached_frustumplanes[i];
3196                 Con_Printf("light %p plane #%i %f %f %f : %f (%f %f %f %f %f)\n", rtlight, i, plane.normal[0], plane.normal[1], plane.normal[2], plane.dist, PlaneDiff(r_refdef.view.frustumcorner[0], &plane), PlaneDiff(r_refdef.view.frustumcorner[1], &plane), PlaneDiff(r_refdef.view.frustumcorner[2], &plane), PlaneDiff(r_refdef.view.frustumcorner[3], &plane), PlaneDiff(rtlight->shadoworigin, &plane));
3197         }
3198 #endif
3199
3200 #if 0
3201         // now add the light-space box planes if the light box is rotated, as any
3202         // caster outside the oriented light box is irrelevant (even if it passed
3203         // the worldspace light box, which is axial)
3204         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
3205         {
3206                 for (i = 0;i < 6;i++)
3207                 {
3208                         vec3_t v;
3209                         VectorClear(v);
3210                         v[i >> 1] = (i & 1) ? -1 : 1;
3211                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
3212                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
3213                         plane.dist = VectorNormalizeLength(plane.normal);
3214                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
3215                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3216                 }
3217         }
3218 #endif
3219
3220 #if 0
3221         // add the world-space reduced box planes
3222         for (i = 0;i < 6;i++)
3223         {
3224                 VectorClear(plane.normal);
3225                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
3226                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
3227                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3228         }
3229 #endif
3230
3231 #if 0
3232         {
3233         int j, oldnum;
3234         vec3_t points[8];
3235         vec_t bestdist;
3236         // reduce all plane distances to tightly fit the rtlight cull box, which
3237         // is in worldspace
3238         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3239         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3240         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3241         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3242         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3243         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3244         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3245         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3246         oldnum = rtlight->cached_numfrustumplanes;
3247         rtlight->cached_numfrustumplanes = 0;
3248         for (j = 0;j < oldnum;j++)
3249         {
3250                 // find the nearest point on the box to this plane
3251                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
3252                 for (i = 1;i < 8;i++)
3253                 {
3254                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
3255                         if (bestdist > dist)
3256                                 bestdist = dist;
3257                 }
3258                 Con_Printf("light %p %splane #%i %f %f %f : %f < %f\n", rtlight, rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125 ? "^2" : "^1", j, rtlight->cached_frustumplanes[j].normal[0], rtlight->cached_frustumplanes[j].normal[1], rtlight->cached_frustumplanes[j].normal[2], rtlight->cached_frustumplanes[j].dist, bestdist);
3259                 // if the nearest point is near or behind the plane, we want this
3260                 // plane, otherwise the plane is useless as it won't cull anything
3261                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
3262                 {
3263                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
3264                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
3265                 }
3266         }
3267         }
3268 #endif
3269 }
3270
3271 void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
3272 {
3273         shadowmesh_t *mesh;
3274
3275         RSurf_ActiveWorldEntity();
3276
3277         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3278         {
3279                 CHECKGLERROR
3280                 GL_CullFace(GL_NONE);
3281         mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
3282         for (;mesh;mesh = mesh->next)
3283         {
3284                         if (!mesh->sidetotals[r_shadow_shadowmapside])
3285                                 continue;
3286             r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
3287             R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3288             R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3289         }
3290         CHECKGLERROR
3291     }
3292         else if (r_refdef.scene.worldentity->model)
3293                 r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3294
3295         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3296 }
3297
3298 void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
3299 {
3300         qboolean zpass = false;
3301         shadowmesh_t *mesh;
3302         int t, tend;
3303         int surfacelistindex;
3304         msurface_t *surface;
3305
3306         RSurf_ActiveWorldEntity();
3307
3308         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3309         {
3310                 CHECKGLERROR
3311                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
3312                 {
3313                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3314                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
3315                 }
3316                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
3317                 for (;mesh;mesh = mesh->next)
3318                 {
3319                         r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
3320                         R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
3321                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
3322                         {
3323                                 // increment stencil if frontface is infront of depthbuffer
3324                                 GL_CullFace(r_refdef.view.cullface_back);
3325                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR
3326                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3327                                 // decrement stencil if backface is infront of depthbuffer
3328                                 GL_CullFace(r_refdef.view.cullface_front);
3329                                 qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR
3330                         }
3331                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
3332                         {
3333                                 // decrement stencil if backface is behind depthbuffer
3334                                 GL_CullFace(r_refdef.view.cullface_front);
3335                                 qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
3336                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3337                                 // increment stencil if frontface is behind depthbuffer
3338                                 GL_CullFace(r_refdef.view.cullface_back);
3339                                 qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
3340                         }
3341                         R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s);
3342                 }
3343                 CHECKGLERROR
3344         }
3345         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
3346         {
3347                 // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
3348                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
3349                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3350                 {
3351                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
3352                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
3353                                 if (CHECKPVSBIT(trispvs, t))
3354                                         shadowmarklist[numshadowmark++] = t;
3355                 }
3356                 R_Shadow_VolumeFromList(r_refdef.scene.worldmodel->brush.shadowmesh->numverts, r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles, r_refdef.scene.worldmodel->brush.shadowmesh->vertex3f, r_refdef.scene.worldmodel->brush.shadowmesh->element3i, r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.scene.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist, r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3357         }
3358         else if (numsurfaces)
3359                 r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3360
3361         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3362 }
3363
3364 void R_Shadow_DrawEntityShadow(entity_render_t *ent)
3365 {
3366         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
3367         vec_t relativeshadowradius;
3368         RSurf_ActiveModelEntity(ent, false, false, false);
3369         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
3370         // we need to re-init the shader for each entity because the matrix changed
3371         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
3372         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
3373         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
3374         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
3375         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
3376         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
3377         relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
3378         switch (r_shadow_rendermode)
3379         {
3380         case R_SHADOW_RENDERMODE_SHADOWMAP2D:
3381         case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE:
3382         case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
3383                 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
3384                 break;
3385         default:
3386                 ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
3387                 break;
3388         }
3389         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3390 }
3391
3392 void R_Shadow_SetupEntityLight(const entity_render_t *ent)
3393 {
3394         // set up properties for rendering light onto this entity
3395         RSurf_ActiveModelEntity(ent, true, true, false);
3396         GL_AlphaTest(false);
3397         Matrix4x4_Concat(&rsurface.entitytolight, &rsurface.rtlight->matrix_worldtolight, &ent->matrix);
3398         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3399         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3400         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3401 }
3402
3403 void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
3404 {
3405         if (!r_refdef.scene.worldmodel->DrawLight)
3406                 return;
3407
3408         // set up properties for rendering light onto this entity
3409         RSurf_ActiveWorldEntity();
3410         GL_AlphaTest(false);
3411         rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight;
3412         Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight);
3413         Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight);
3414         VectorCopy(rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
3415
3416         r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
3417
3418         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3419 }
3420
3421 void R_Shadow_DrawEntityLight(entity_render_t *ent)
3422 {
3423         dp_model_t *model = ent->model;
3424         if (!model->DrawLight)
3425                 return;
3426
3427         R_Shadow_SetupEntityLight(ent);
3428
3429         model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
3430
3431         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3432 }
3433
3434 void R_Shadow_PrepareLight(rtlight_t *rtlight)
3435 {
3436         int i;
3437         float f;
3438         int numleafs, numsurfaces;
3439         int *leaflist, *surfacelist;
3440         unsigned char *leafpvs;
3441         unsigned char *shadowtrispvs;
3442         unsigned char *lighttrispvs;
3443         //unsigned char *surfacesides;
3444         int numlightentities;
3445         int numlightentities_noselfshadow;
3446         int numshadowentities;
3447         int numshadowentities_noselfshadow;
3448         static entity_render_t *lightentities[MAX_EDICTS];
3449         static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
3450         static entity_render_t *shadowentities[MAX_EDICTS];
3451         static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
3452
3453         rtlight->draw = false;
3454
3455         // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
3456         // skip lights that are basically invisible (color 0 0 0)
3457         if (VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f))
3458                 return;
3459
3460         // loading is done before visibility checks because loading should happen
3461         // all at once at the start of a level, not when it stalls gameplay.
3462         // (especially important to benchmarks)
3463         // compile light
3464         if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
3465         {
3466                 if (rtlight->compiled)
3467                         R_RTLight_Uncompile(rtlight);
3468                 R_RTLight_Compile(rtlight);
3469         }
3470
3471         // load cubemap
3472         rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
3473
3474         // look up the light style value at this time
3475         f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
3476         VectorScale(rtlight->color, f, rtlight->currentcolor);
3477         /*
3478         if (rtlight->selected)
3479         {
3480                 f = 2 + sin(realtime * M_PI * 4.0);
3481                 VectorScale(rtlight->currentcolor, f, rtlight->currentcolor);
3482         }
3483         */
3484
3485         // if lightstyle is currently off, don't draw the light
3486         if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
3487                 return;
3488
3489         // if the light box is offscreen, skip it
3490         if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
3491                 return;
3492
3493         VectorCopy(rtlight->cullmins, rtlight->cached_cullmins);
3494         VectorCopy(rtlight->cullmaxs, rtlight->cached_cullmaxs);
3495
3496         R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
3497
3498         if (rtlight->compiled && r_shadow_realtime_world_compile.integer)
3499         {
3500                 // compiled light, world available and can receive realtime lighting
3501                 // retrieve leaf information
3502                 numleafs = rtlight->static_numleafs;
3503                 leaflist = rtlight->static_leaflist;
3504                 leafpvs = rtlight->static_leafpvs;
3505                 numsurfaces = rtlight->static_numsurfaces;
3506                 surfacelist = rtlight->static_surfacelist;
3507                 //surfacesides = NULL;
3508                 shadowtrispvs = rtlight->static_shadowtrispvs;
3509                 lighttrispvs = rtlight->static_lighttrispvs;
3510         }
3511         else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->GetLightInfo)
3512         {
3513                 // dynamic light, world available and can receive realtime lighting
3514                 // calculate lit surfaces and leafs
3515                 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);
3516                 R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
3517                 leaflist = r_shadow_buffer_leaflist;
3518                 leafpvs = r_shadow_buffer_leafpvs;
3519                 surfacelist = r_shadow_buffer_surfacelist;
3520                 //surfacesides = r_shadow_buffer_surfacesides;
3521                 shadowtrispvs = r_shadow_buffer_shadowtrispvs;
3522                 lighttrispvs = r_shadow_buffer_lighttrispvs;
3523                 // if the reduced leaf bounds are offscreen, skip it
3524                 if (R_CullBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
3525                         return;
3526         }
3527         else
3528         {
3529                 // no world
3530                 numleafs = 0;
3531                 leaflist = NULL;
3532                 leafpvs = NULL;
3533                 numsurfaces = 0;
3534                 surfacelist = NULL;
3535                 //surfacesides = NULL;
3536                 shadowtrispvs = NULL;
3537                 lighttrispvs = NULL;
3538         }
3539         // check if light is illuminating any visible leafs
3540         if (numleafs)
3541         {
3542                 for (i = 0;i < numleafs;i++)
3543                         if (r_refdef.viewcache.world_leafvisible[leaflist[i]])
3544                                 break;
3545                 if (i == numleafs)
3546                         return;
3547         }
3548
3549         // make a list of lit entities and shadow casting entities
3550         numlightentities = 0;
3551         numlightentities_noselfshadow = 0;
3552         numshadowentities = 0;
3553         numshadowentities_noselfshadow = 0;
3554
3555         // add dynamic entities that are lit by the light
3556         for (i = 0;i < r_refdef.scene.numentities;i++)
3557         {
3558                 dp_model_t *model;
3559                 entity_render_t *ent = r_refdef.scene.entities[i];
3560                 vec3_t org;
3561                 if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
3562                         continue;
3563                 // skip the object entirely if it is not within the valid
3564                 // shadow-casting region (which includes the lit region)
3565                 if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
3566                         continue;
3567                 if (!(model = ent->model))
3568                         continue;
3569                 if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
3570                 {
3571                         // this entity wants to receive light, is visible, and is
3572                         // inside the light box
3573                         // TODO: check if the surfaces in the model can receive light
3574                         // so now check if it's in a leaf seen by the light
3575                         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))
3576                                 continue;
3577                         if (ent->flags & RENDER_NOSELFSHADOW)
3578                                 lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
3579                         else
3580                                 lightentities[numlightentities++] = ent;
3581                         // since it is lit, it probably also casts a shadow...
3582                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
3583                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3584                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
3585                         {
3586                                 // note: exterior models without the RENDER_NOSELFSHADOW
3587                                 // flag still create a RENDER_NOSELFSHADOW shadow but
3588                                 // are lit normally, this means that they are
3589                                 // self-shadowing but do not shadow other
3590                                 // RENDER_NOSELFSHADOW entities such as the gun
3591                                 // (very weird, but keeps the player shadow off the gun)
3592                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
3593                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
3594                                 else
3595                                         shadowentities[numshadowentities++] = ent;
3596                         }
3597                 }
3598                 else if (ent->flags & RENDER_SHADOW)
3599                 {
3600                         // this entity is not receiving light, but may still need to
3601                         // cast a shadow...
3602                         // TODO: check if the surfaces in the model can cast shadow
3603                         // now check if it is in a leaf seen by the light
3604                         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))
3605                                 continue;
3606                         // about the VectorDistance2 - light emitting entities should not cast their own shadow
3607                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3608                         if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
3609                         {
3610                                 if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
3611                                         shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
3612                                 else
3613                                         shadowentities[numshadowentities++] = ent;
3614                         }
3615                 }
3616         }
3617
3618         // return if there's nothing at all to light
3619         if (numsurfaces + numlightentities + numlightentities_noselfshadow == 0)
3620                 return;
3621
3622         // count this light in the r_speeds
3623         r_refdef.stats.lights++;
3624
3625         // flag it as worth drawing later
3626         rtlight->draw = true;
3627
3628         // cache all the animated entities that cast a shadow but are not visible
3629         for (i = 0;i < numshadowentities;i++)
3630                 if (!shadowentities[i]->animcache_vertex3f)
3631                         R_AnimCache_GetEntity(shadowentities[i], false, false);
3632         for (i = 0;i < numshadowentities_noselfshadow;i++)
3633                 if (!shadowentities_noselfshadow[i]->animcache_vertex3f)
3634                         R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
3635
3636         // allocate some temporary memory for rendering this light later in the frame
3637         // reusable buffers need to be copied, static data can be used as-is
3638         rtlight->cached_numlightentities               = numlightentities;
3639         rtlight->cached_numlightentities_noselfshadow  = numlightentities_noselfshadow;
3640         rtlight->cached_numshadowentities              = numshadowentities;
3641         rtlight->cached_numshadowentities_noselfshadow = numshadowentities_noselfshadow;
3642         rtlight->cached_numsurfaces                    = numsurfaces;
3643         rtlight->cached_lightentities                  = (entity_render_t**)R_FrameData_Store(numlightentities*sizeof(entity_render_t*), (void*)lightentities);
3644         rtlight->cached_lightentities_noselfshadow     = (entity_render_t**)R_FrameData_Store(numlightentities_noselfshadow*sizeof(entity_render_t*), (void*)lightentities_noselfshadow);
3645         rtlight->cached_shadowentities                 = (entity_render_t**)R_FrameData_Store(numshadowentities*sizeof(entity_render_t*), (void*)shadowentities);
3646         rtlight->cached_shadowentities_noselfshadow    = (entity_render_t**)R_FrameData_Store(numshadowentities_noselfshadow*sizeof(entity_render_t *), (void*)shadowentities_noselfshadow);
3647         if (shadowtrispvs == r_shadow_buffer_shadowtrispvs)
3648         {
3649                 int numshadowtrispvsbytes = (((r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles) + 7) >> 3);
3650                 int numlighttrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
3651                 rtlight->cached_shadowtrispvs                  =   (unsigned char *)R_FrameData_Store(numshadowtrispvsbytes, shadowtrispvs);
3652                 rtlight->cached_lighttrispvs                   =   (unsigned char *)R_FrameData_Store(numlighttrispvsbytes, lighttrispvs);
3653                 rtlight->cached_surfacelist                    =              (int*)R_FrameData_Store(numsurfaces*sizeof(int), (void*)surfacelist);
3654         }
3655         else
3656         {
3657                 // compiled light data
3658                 rtlight->cached_shadowtrispvs = shadowtrispvs;
3659                 rtlight->cached_lighttrispvs = lighttrispvs;
3660                 rtlight->cached_surfacelist = surfacelist;
3661         }
3662 }
3663
3664 void R_Shadow_DrawLight(rtlight_t *rtlight)
3665 {
3666         int i;
3667         int numsurfaces;
3668         unsigned char *shadowtrispvs, *lighttrispvs, *surfacesides;
3669         int numlightentities;
3670         int numlightentities_noselfshadow;
3671         int numshadowentities;
3672         int numshadowentities_noselfshadow;
3673         entity_render_t **lightentities;
3674         entity_render_t **lightentities_noselfshadow;
3675         entity_render_t **shadowentities;
3676         entity_render_t **shadowentities_noselfshadow;
3677         int *surfacelist;
3678         static unsigned char entitysides[MAX_EDICTS];
3679         static unsigned char entitysides_noselfshadow[MAX_EDICTS];
3680         vec3_t nearestpoint;
3681         vec_t distance;
3682         qboolean castshadows;
3683         int lodlinear;
3684
3685         // check if we cached this light this frame (meaning it is worth drawing)
3686         if (!rtlight->draw)
3687                 return;
3688
3689         // if R_FrameData_Store ran out of space we skip anything dependent on it
3690         if (r_framedata_failed)
3691                 return;
3692
3693         numlightentities = rtlight->cached_numlightentities;
3694         numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
3695         numshadowentities = rtlight->cached_numshadowentities;
3696         numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
3697         numsurfaces = rtlight->cached_numsurfaces;
3698         lightentities = rtlight->cached_lightentities;
3699         lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
3700         shadowentities = rtlight->cached_shadowentities;
3701         shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
3702         shadowtrispvs = rtlight->cached_shadowtrispvs;
3703         lighttrispvs = rtlight->cached_lighttrispvs;
3704         surfacelist = rtlight->cached_surfacelist;
3705
3706         // set up a scissor rectangle for this light
3707         if (R_Shadow_ScissorForBBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
3708                 return;
3709
3710         // don't let sound skip if going slow
3711         if (r_refdef.scene.extraupdate)
3712                 S_ExtraUpdate ();
3713
3714         // make this the active rtlight for rendering purposes
3715         R_Shadow_RenderMode_ActiveLight(rtlight);
3716
3717         if (r_showshadowvolumes.integer && r_refdef.view.showdebug && numsurfaces + numshadowentities + numshadowentities_noselfshadow && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows))
3718         {
3719                 // optionally draw visible shape of the shadow volumes
3720                 // for performance analysis by level designers
3721                 R_Shadow_RenderMode_VisibleShadowVolumes();
3722                 if (numsurfaces)
3723                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
3724                 for (i = 0;i < numshadowentities;i++)
3725                         R_Shadow_DrawEntityShadow(shadowentities[i]);
3726                 for (i = 0;i < numshadowentities_noselfshadow;i++)
3727                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
3728                 R_Shadow_RenderMode_VisibleLighting(false, false);
3729         }
3730
3731         if (r_showlighting.integer && r_refdef.view.showdebug && numsurfaces + numlightentities + numlightentities_noselfshadow)
3732         {
3733                 // optionally draw the illuminated areas
3734                 // for performance analysis by level designers
3735                 R_Shadow_RenderMode_VisibleLighting(false, false);
3736                 if (numsurfaces)
3737                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3738                 for (i = 0;i < numlightentities;i++)
3739                         R_Shadow_DrawEntityLight(lightentities[i]);
3740                 for (i = 0;i < numlightentities_noselfshadow;i++)
3741                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3742         }
3743
3744         castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
3745
3746         nearestpoint[0] = bound(rtlight->cullmins[0], r_refdef.view.origin[0], rtlight->cullmaxs[0]);
3747         nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
3748         nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
3749         distance = VectorDistance(nearestpoint, r_refdef.view.origin);
3750
3751         lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance/rtlight->radius));
3752         //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
3753         lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
3754
3755         if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
3756         {
3757                 float borderbias;
3758                 int side;
3759                 int size;
3760                 int castermask = 0;
3761                 int receivermask = 0;
3762                 matrix4x4_t radiustolight = rtlight->matrix_worldtolight;
3763                 Matrix4x4_Abs(&radiustolight);
3764
3765                 r_shadow_shadowmaplod = 0;
3766                 for (i = 1;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
3767                         if ((r_shadow_shadowmapmaxsize >> i) > lodlinear)
3768                                 r_shadow_shadowmaplod = i;
3769
3770                 if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
3771                         size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod);
3772                 else
3773                         size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
3774                         
3775                 borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
3776
3777                 surfacesides = NULL;
3778                 if (numsurfaces)
3779                 {
3780                         if (rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3781                         {
3782                                 castermask = rtlight->static_shadowmap_casters;
3783                                 receivermask = rtlight->static_shadowmap_receivers;
3784                         }
3785                         else
3786                         {
3787                                 surfacesides = r_shadow_buffer_surfacesides;
3788                                 for(i = 0;i < numsurfaces;i++)
3789                                 {
3790                                         msurface_t *surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[i];
3791                                         surfacesides[i] = R_Shadow_CalcBBoxSideMask(surface->mins, surface->maxs, &rtlight->matrix_worldtolight, &radiustolight, borderbias);           
3792                                         castermask |= surfacesides[i];
3793                                         receivermask |= surfacesides[i];
3794                                 }
3795                         }
3796                 }
3797                 if (receivermask < 0x3F) 
3798                 {
3799                         for (i = 0;i < numlightentities;i++)
3800                                 receivermask |= R_Shadow_CalcEntitySideMask(lightentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
3801                         if (receivermask < 0x3F)
3802                                 for(i = 0; i < numlightentities_noselfshadow;i++)
3803                                         receivermask |= R_Shadow_CalcEntitySideMask(lightentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
3804                 }
3805
3806                 receivermask &= R_Shadow_CullFrustumSides(rtlight, size, r_shadow_shadowmapborder);
3807
3808                 if (receivermask)
3809                 {
3810                         for (i = 0;i < numshadowentities;i++)
3811                                 castermask |= (entitysides[i] = R_Shadow_CalcEntitySideMask(shadowentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
3812                         for (i = 0;i < numshadowentities_noselfshadow;i++)
3813                                 castermask |= (entitysides_noselfshadow[i] = R_Shadow_CalcEntitySideMask(shadowentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias)); 
3814                 }
3815
3816                 //Con_Printf("distance %f lodlinear %i (lod %i) size %i\n", distance, lodlinear, r_shadow_shadowmaplod, size);
3817
3818                 // render shadow casters into 6 sided depth texture
3819                 for (side = 0;side < 6;side++) if (receivermask & (1 << side))
3820                 {
3821                         R_Shadow_RenderMode_ShadowMap(side, receivermask, size);
3822                         if (! (castermask & (1 << side))) continue;
3823                         if (numsurfaces)
3824                                 R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
3825                         for (i = 0;i < numshadowentities;i++) if (entitysides[i] & (1 << side))
3826                                 R_Shadow_DrawEntityShadow(shadowentities[i]);
3827                 }
3828
3829                 if (numlightentities_noselfshadow)
3830                 {
3831                         // render lighting using the depth texture as shadowmap
3832                         // draw lighting in the unmasked areas
3833                         R_Shadow_RenderMode_Lighting(false, false, true);
3834                         for (i = 0;i < numlightentities_noselfshadow;i++)
3835                                 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3836                 }
3837
3838                 // render shadow casters into 6 sided depth texture
3839                 if (numshadowentities_noselfshadow)
3840                 {
3841                         for (side = 0;side < 6;side++) if ((receivermask & castermask) & (1 << side))
3842                         {
3843                                 R_Shadow_RenderMode_ShadowMap(side, 0, size);
3844                                 for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides_noselfshadow[i] & (1 << side))
3845                                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
3846                         }
3847                 }
3848
3849                 // render lighting using the depth texture as shadowmap
3850                 // draw lighting in the unmasked areas
3851                 R_Shadow_RenderMode_Lighting(false, false, true);
3852                 // draw lighting in the unmasked areas
3853                 if (numsurfaces)
3854                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3855                 for (i = 0;i < numlightentities;i++)
3856                         R_Shadow_DrawEntityLight(lightentities[i]);
3857         }
3858         else if (castshadows && vid.stencil)
3859         {
3860                 // draw stencil shadow volumes to mask off pixels that are in shadow
3861                 // so that they won't receive lighting
3862                 GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
3863                 R_Shadow_ClearStencil();
3864
3865                 if (numsurfaces)
3866                         R_Shadow_DrawWorldShadow_ShadowVolume(numsurfaces, surfacelist, shadowtrispvs);
3867                 for (i = 0;i < numshadowentities;i++)
3868                         R_Shadow_DrawEntityShadow(shadowentities[i]);
3869
3870                 // draw lighting in the unmasked areas
3871                 R_Shadow_RenderMode_Lighting(true, false, false);
3872                 for (i = 0;i < numlightentities_noselfshadow;i++)
3873                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3874
3875                 for (i = 0;i < numshadowentities_noselfshadow;i++)
3876                         R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
3877
3878                 // draw lighting in the unmasked areas
3879                 R_Shadow_RenderMode_Lighting(true, false, false);
3880                 if (numsurfaces)
3881                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3882                 for (i = 0;i < numlightentities;i++)
3883                         R_Shadow_DrawEntityLight(lightentities[i]);
3884         }
3885         else
3886         {
3887                 // draw lighting in the unmasked areas
3888                 R_Shadow_RenderMode_Lighting(false, false, false);
3889                 if (numsurfaces)
3890                         R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3891                 for (i = 0;i < numlightentities;i++)
3892                         R_Shadow_DrawEntityLight(lightentities[i]);
3893                 for (i = 0;i < numlightentities_noselfshadow;i++)
3894                         R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3895         }
3896
3897         if (r_shadow_usingdeferredprepass)
3898         {
3899                 // when rendering deferred lighting, we simply rasterize the box
3900                 if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
3901                         R_Shadow_RenderMode_DrawDeferredLight(false, true);
3902                 else if (castshadows && vid.stencil)
3903                         R_Shadow_RenderMode_DrawDeferredLight(true, false);
3904                 else
3905                         R_Shadow_RenderMode_DrawDeferredLight(false, false);
3906         }
3907 }
3908
3909 static void R_Shadow_FreeDeferred(void)
3910 {
3911         if (r_shadow_prepassgeometryfbo)
3912                 qglDeleteFramebuffersEXT(1, &r_shadow_prepassgeometryfbo);CHECKGLERROR
3913         r_shadow_prepassgeometryfbo = 0;
3914
3915         if (r_shadow_prepasslightingfbo)
3916                 qglDeleteFramebuffersEXT(1, &r_shadow_prepasslightingfbo);CHECKGLERROR
3917         r_shadow_prepasslightingfbo = 0;
3918
3919         if (r_shadow_prepassgeometrydepthtexture)
3920                 R_FreeTexture(r_shadow_prepassgeometrydepthtexture);
3921         r_shadow_prepassgeometrydepthtexture = NULL;
3922
3923         if (r_shadow_prepassgeometrynormalmaptexture)
3924                 R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
3925         r_shadow_prepassgeometrynormalmaptexture = NULL;
3926
3927         if (r_shadow_prepasslightingdiffusetexture)
3928                 R_FreeTexture(r_shadow_prepasslightingdiffusetexture);
3929         r_shadow_prepasslightingdiffusetexture = NULL;
3930
3931         if (r_shadow_prepasslightingspeculartexture)
3932                 R_FreeTexture(r_shadow_prepasslightingspeculartexture);
3933         r_shadow_prepasslightingspeculartexture = NULL;
3934 }
3935
3936 void R_Shadow_DrawPrepass(void)
3937 {
3938         int i;
3939         int flag;
3940         int lnum;
3941         size_t lightindex;
3942         dlight_t *light;
3943         size_t range;
3944         entity_render_t *ent;
3945
3946         GL_AlphaTest(false);
3947         R_Mesh_ColorPointer(NULL, 0, 0);
3948         R_Mesh_ResetTextureState();
3949         GL_DepthMask(true);
3950         GL_ColorMask(1,1,1,1);
3951         GL_BlendFunc(GL_ONE, GL_ZERO);
3952         GL_Color(1,1,1,1);
3953         GL_DepthTest(true);
3954         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepassgeometryfbo);CHECKGLERROR
3955         qglClearColor(0.5f,0.5f,0.5f,1.0f);CHECKGLERROR
3956         GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);CHECKGLERROR
3957
3958         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawPrepass)
3959                 r_refdef.scene.worldmodel->DrawPrepass(r_refdef.scene.worldentity);
3960         if (r_timereport_active)
3961                 R_TimeReport("prepassworld");
3962
3963         for (i = 0;i < r_refdef.scene.numentities;i++)
3964         {
3965                 if (!r_refdef.viewcache.entityvisible[i])
3966                         continue;
3967                 ent = r_refdef.scene.entities[i];
3968                 if (ent->model && ent->model->DrawPrepass != NULL)
3969                         ent->model->DrawPrepass(ent);
3970         }
3971
3972         if (r_timereport_active)
3973                 R_TimeReport("prepassmodels");
3974
3975         GL_DepthMask(false);
3976         GL_ColorMask(1,1,1,1);
3977         GL_Color(1,1,1,1);
3978         GL_DepthTest(true);
3979         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
3980         qglClearColor(0.0f,0.0f,0.0f,0.0f);CHECKGLERROR
3981         GL_Clear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3982         if (r_refdef.fogenabled)
3983                 qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
3984
3985         R_Shadow_RenderMode_Begin();
3986
3987         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
3988         if (r_shadow_debuglight.integer >= 0)
3989         {
3990                 lightindex = r_shadow_debuglight.integer;
3991                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3992                 if (light && (light->flags & flag))
3993                         R_Shadow_DrawLight(&light->rtlight);
3994         }
3995         else
3996         {
3997                 range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3998                 for (lightindex = 0;lightindex < range;lightindex++)
3999                 {
4000                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4001                         if (light && (light->flags & flag))
4002                                 R_Shadow_DrawLight(&light->rtlight);
4003                 }
4004         }
4005         if (r_refdef.scene.rtdlight)
4006                 for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
4007                         R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
4008
4009         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
4010         if (r_refdef.fogenabled)
4011                 qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
4012
4013         R_Shadow_RenderMode_End();
4014
4015         if (r_timereport_active)
4016                 R_TimeReport("prepasslights");
4017 }
4018
4019 void R_Shadow_DrawLightSprites(void);
4020 void R_Shadow_PrepareLights(void)
4021 {
4022         int flag;
4023         int lnum;
4024         size_t lightindex;
4025         dlight_t *light;
4026         size_t range;
4027         float f;
4028         GLenum status;
4029
4030         if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) ||
4031                 (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
4032                 r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || 
4033                 r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
4034                 r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || 
4035                 r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer || 
4036                 r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
4037                 R_Shadow_FreeShadowMaps();
4038
4039         r_shadow_usingshadowmaportho = false;
4040
4041         switch (vid.renderpath)
4042         {
4043         case RENDERPATH_GL20:
4044         case RENDERPATH_CGGL:
4045                 if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
4046                 {
4047                         r_shadow_usingdeferredprepass = false;
4048                         if (r_shadow_prepass_width)
4049                                 R_Shadow_FreeDeferred();
4050                         r_shadow_prepass_width = r_shadow_prepass_height = 0;
4051                         break;
4052                 }
4053
4054                 if (r_shadow_prepass_width != vid.width || r_shadow_prepass_height != vid.height)
4055                 {
4056                         R_Shadow_FreeDeferred();
4057
4058                         r_shadow_usingdeferredprepass = true;
4059                         r_shadow_prepass_width = vid.width;
4060                         r_shadow_prepass_height = vid.height;
4061                         r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false);
4062                         r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
4063                         r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
4064                         r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, NULL);
4065
4066                         // set up the geometry pass fbo (depth + normalmap)
4067                         qglGenFramebuffersEXT(1, &r_shadow_prepassgeometryfbo);CHECKGLERROR
4068                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepassgeometryfbo);CHECKGLERROR
4069                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrydepthtexture), 0);CHECKGLERROR
4070                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture), 0);CHECKGLERROR
4071                         // render depth into one texture and normalmap into the other
4072                         if (qglDrawBuffersARB)
4073                         {
4074                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
4075                                 qglReadBuffer(GL_NONE);CHECKGLERROR
4076                         }
4077                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
4078                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
4079                         {
4080                                 Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
4081                                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
4082                                 r_shadow_usingdeferredprepass = false;
4083                         }
4084
4085                         // set up the lighting pass fbo (diffuse + specular)
4086                         qglGenFramebuffersEXT(1, &r_shadow_prepasslightingfbo);CHECKGLERROR
4087                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_prepasslightingfbo);CHECKGLERROR
4088                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepassgeometrydepthtexture), 0);CHECKGLERROR
4089                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepasslightingdiffusetexture), 0);CHECKGLERROR
4090                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_prepasslightingspeculartexture), 0);CHECKGLERROR
4091                         // render diffuse into one texture and specular into another,
4092                         // with depth and normalmap bound as textures,
4093                         // with depth bound as attachment as well
4094                         if (qglDrawBuffersARB)
4095                         {
4096                                 qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR
4097                                 qglReadBuffer(GL_NONE);CHECKGLERROR
4098                         }
4099                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
4100                         if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
4101                         {
4102                                 Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
4103                                 Cvar_SetValueQuick(&r_shadow_deferred, 0);
4104                                 r_shadow_usingdeferredprepass = false;
4105                         }
4106                 }
4107                 break;
4108         case RENDERPATH_GL13:
4109         case RENDERPATH_GL11:
4110                 r_shadow_usingdeferredprepass = false;
4111                 break;
4112         }
4113
4114         R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
4115
4116         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
4117         if (r_shadow_debuglight.integer >= 0)
4118         {
4119                 lightindex = r_shadow_debuglight.integer;
4120                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4121                 if (light && (light->flags & flag))
4122                         R_Shadow_PrepareLight(&light->rtlight);
4123         }
4124         else
4125         {
4126                 range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4127                 for (lightindex = 0;lightindex < range;lightindex++)
4128                 {
4129                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4130                         if (light && (light->flags & flag))
4131                                 R_Shadow_PrepareLight(&light->rtlight);
4132                 }
4133         }
4134         if (r_refdef.scene.rtdlight)
4135         {
4136                 for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
4137                         R_Shadow_PrepareLight(r_refdef.scene.lights[lnum]);
4138         }
4139         else if(gl_flashblend.integer)
4140         {
4141                 for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
4142                 {
4143                         rtlight_t *rtlight = r_refdef.scene.lights[lnum];
4144                         f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
4145                         VectorScale(rtlight->color, f, rtlight->currentcolor);
4146                 }
4147         }
4148
4149         if (r_editlights.integer)
4150                 R_Shadow_DrawLightSprites();
4151 }
4152
4153 void R_Shadow_DrawLights(void)
4154 {
4155         int flag;
4156         int lnum;
4157         size_t lightindex;
4158         dlight_t *light;
4159         size_t range;
4160
4161         R_Shadow_RenderMode_Begin();
4162
4163         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
4164         if (r_shadow_debuglight.integer >= 0)
4165         {
4166                 lightindex = r_shadow_debuglight.integer;
4167                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4168                 if (light && (light->flags & flag))
4169                         R_Shadow_DrawLight(&light->rtlight);
4170         }
4171         else
4172         {
4173                 range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4174                 for (lightindex = 0;lightindex < range;lightindex++)
4175                 {
4176                         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4177                         if (light && (light->flags & flag))
4178                                 R_Shadow_DrawLight(&light->rtlight);
4179                 }
4180         }
4181         if (r_refdef.scene.rtdlight)
4182                 for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
4183                         R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
4184
4185         R_Shadow_RenderMode_End();
4186 }
4187
4188 extern const float r_screenvertex3f[12];
4189 extern void R_SetupView(qboolean allowwaterclippingplane);
4190 extern void R_ResetViewRendering3D(void);
4191 extern void R_ResetViewRendering2D(void);
4192 extern cvar_t r_shadows;
4193 extern cvar_t r_shadows_darken;
4194 extern cvar_t r_shadows_drawafterrtlighting;
4195 extern cvar_t r_shadows_castfrombmodels;
4196 extern cvar_t r_shadows_throwdistance;
4197 extern cvar_t r_shadows_throwdirection;
4198
4199 void R_DrawModelShadowMaps(void)
4200 {
4201         int i;
4202         float relativethrowdistance, scale, size, nearclip, farclip, dot1, dot2;
4203         entity_render_t *ent;
4204         vec3_t relativelightorigin;
4205         vec3_t relativelightdirection;
4206         vec3_t relativeshadowmins, relativeshadowmaxs;
4207         vec3_t shadowdir, shadowforward;
4208         float m[12];
4209         matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix;
4210         r_viewport_t viewport;
4211         GLuint fbo = 0;
4212
4213         if (!r_refdef.scene.numentities)
4214                 return;
4215
4216         switch (r_shadow_shadowmode)
4217         {
4218         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
4219         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
4220                 break;
4221         default:
4222                 return;
4223         }
4224
4225         CHECKGLERROR
4226         R_ResetViewRendering3D();
4227         R_Shadow_RenderMode_Begin();
4228         R_Shadow_RenderMode_ActiveLight(NULL);
4229
4230         switch (r_shadow_shadowmode)
4231         {
4232         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
4233                 if (!r_shadow_shadowmap2dtexture)
4234                         R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
4235                 fbo = r_shadow_fbo2d;
4236                 r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
4237                 r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
4238                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
4239                 break;
4240         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
4241                 if (!r_shadow_shadowmaprectangletexture)
4242                         R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
4243                 fbo = r_shadow_fborectangle;
4244                 r_shadow_shadowmap_texturescale[0] = 1.0f;
4245                 r_shadow_shadowmap_texturescale[1] = 1.0f;
4246                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
4247                 break;
4248         default:
4249                 break;
4250         }
4251
4252         size = 2*r_shadow_shadowmapmaxsize;
4253
4254         r_shadow_shadowmap_parameters[0] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
4255         r_shadow_shadowmap_parameters[1] = 1.0f;
4256         r_shadow_shadowmap_parameters[2] = size;
4257         r_shadow_shadowmap_parameters[3] = size;
4258
4259         scale = r_shadow_shadowmapping_precision.value;
4260         nearclip = -r_shadows_throwdistance.value;
4261         farclip = r_shadows_throwdistance.value;
4262         Math_atov(r_shadows_throwdirection.string, shadowdir);
4263         VectorNormalize(shadowdir);
4264         dot1 = DotProduct(r_refdef.view.forward, shadowdir);
4265         dot2 = DotProduct(r_refdef.view.up, shadowdir);
4266         if (fabs(dot1) <= fabs(dot2)) 
4267                 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
4268         else
4269                 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
4270         VectorNormalize(shadowforward);
4271         VectorM(scale, shadowforward, &m[0]);
4272         m[3] = fabs(dot1) * 0.5f * size - DotProduct(r_refdef.view.origin, &m[0]);
4273         CrossProduct(shadowdir, shadowforward, &m[4]);
4274         VectorM(scale, &m[4], &m[4]);
4275         m[7] = 0.5f * size - DotProduct(r_refdef.view.origin, &m[4]);
4276         VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
4277         m[11] = 0.5f - DotProduct(r_refdef.view.origin, &m[8]);
4278         Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
4279         Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
4280         R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, size, size, 0, 0, -1, NULL); 
4281
4282 #if 0
4283         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
4284         R_SetupShader_ShowDepth();
4285 #else
4286         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
4287         R_SetupShader_DepthOrShadow();
4288 #endif
4289         CHECKGLERROR
4290         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
4291         GL_DepthMask(true);
4292         GL_DepthTest(true);
4293         R_SetViewport(&viewport);
4294         GL_Scissor(viewport.x, viewport.y, viewport.width + r_shadow_shadowmapborder, viewport.height + r_shadow_shadowmapborder);
4295         qglClearDepth(1);
4296 #if 0
4297         qglClearColor(1,1,1,1);
4298         GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4299 #else
4300         GL_Clear(GL_DEPTH_BUFFER_BIT);
4301 #endif
4302         GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
4303         CHECKGLERROR
4304
4305         for (i = 0;i < r_refdef.scene.numentities;i++)
4306         {
4307                 ent = r_refdef.scene.entities[i];
4308
4309                 // cast shadows from anything of the map (submodels are optional)
4310                 if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
4311                 {
4312                         relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
4313                         VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
4314                         VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
4315                         Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
4316                         VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
4317                         RSurf_ActiveModelEntity(ent, false, false, false);
4318                         ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
4319                         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4320                 }
4321         }
4322
4323         R_Shadow_RenderMode_End();
4324
4325         Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
4326         Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
4327         Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &shadowmatrix, &invmvpmatrix);
4328
4329         r_shadow_usingshadowmaportho = true;
4330         switch (r_shadow_shadowmode)
4331         {
4332         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
4333                 r_shadow_usingshadowmap2d = true;
4334                 break;
4335         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
4336                 r_shadow_usingshadowmaprect = true;
4337                 break;
4338         default:
4339                 break;
4340         }
4341 }
4342
4343 void R_DrawModelShadows(void)
4344 {
4345         int i;
4346         float relativethrowdistance;
4347         entity_render_t *ent;
4348         vec3_t relativelightorigin;
4349         vec3_t relativelightdirection;
4350         vec3_t relativeshadowmins, relativeshadowmaxs;
4351         vec3_t tmp, shadowdir;
4352
4353         if (!r_refdef.scene.numentities || !vid.stencil || r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL)
4354                 return;
4355
4356         CHECKGLERROR
4357         R_ResetViewRendering3D();
4358         //GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4359         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
4360         R_Shadow_RenderMode_Begin();
4361         R_Shadow_RenderMode_ActiveLight(NULL);
4362         r_shadow_lightscissor[0] = r_refdef.view.x;
4363         r_shadow_lightscissor[1] = vid.height - r_refdef.view.y - r_refdef.view.height;
4364         r_shadow_lightscissor[2] = r_refdef.view.width;
4365         r_shadow_lightscissor[3] = r_refdef.view.height;
4366         R_Shadow_RenderMode_StencilShadowVolumes(false);
4367
4368         // get shadow dir
4369         if (r_shadows.integer == 2)
4370         {
4371                 Math_atov(r_shadows_throwdirection.string, shadowdir);
4372                 VectorNormalize(shadowdir);
4373         }
4374
4375         R_Shadow_ClearStencil();
4376
4377         for (i = 0;i < r_refdef.scene.numentities;i++)
4378         {
4379                 ent = r_refdef.scene.entities[i];
4380
4381                 // cast shadows from anything of the map (submodels are optional)
4382                 if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
4383                 {
4384                         relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
4385                         VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
4386                         VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
4387                         if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
4388                                 Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
4389                         else
4390                         {
4391                                 if(ent->entitynumber != 0)
4392                                 {
4393                                         // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
4394                                         int entnum, entnum2, recursion;
4395                                         entnum = entnum2 = ent->entitynumber;
4396                                         for(recursion = 32; recursion > 0; --recursion)
4397                                         {
4398                                                 entnum2 = cl.entities[entnum].state_current.tagentity;
4399                                                 if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
4400                                                         entnum = entnum2;
4401                                                 else
4402                                                         break;
4403                                         }
4404                                         if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
4405                                         {
4406                                                 VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
4407                                                 // transform into modelspace of OUR entity
4408                                                 Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
4409                                                 Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
4410                                         }
4411                                         else
4412                                                 VectorNegate(ent->modellight_lightdir, relativelightdirection);
4413                                 }
4414                                 else
4415                                         VectorNegate(ent->modellight_lightdir, relativelightdirection);
4416                         }
4417
4418                         VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
4419                         RSurf_ActiveModelEntity(ent, false, false, false);
4420                         ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
4421                         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4422                 }
4423         }
4424
4425         // not really the right mode, but this will disable any silly stencil features
4426         R_Shadow_RenderMode_End();
4427
4428         // set up ortho view for rendering this pass
4429         //GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
4430         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4431         //GL_ScissorTest(true);
4432         //R_EntityMatrix(&identitymatrix);
4433         //R_Mesh_ResetTextureState();
4434         R_ResetViewRendering2D();
4435         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4436         R_Mesh_ColorPointer(NULL, 0, 0);
4437         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
4438
4439         // set up a darkening blend on shadowed areas
4440         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4441         //GL_DepthRange(0, 1);
4442         //GL_DepthTest(false);
4443         //GL_DepthMask(false);
4444         //GL_PolygonOffset(0, 0);CHECKGLERROR
4445         GL_Color(0, 0, 0, r_shadows_darken.value);
4446         //GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4447         //qglDepthFunc(GL_ALWAYS);CHECKGLERROR
4448         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
4449         qglStencilMask(255);CHECKGLERROR
4450         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4451         qglStencilFunc(GL_NOTEQUAL, 128, 255);CHECKGLERROR
4452
4453         // apply the blend to the shadowed areas
4454         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4455
4456         // restore the viewport
4457         R_SetViewport(&r_refdef.view.viewport);
4458
4459         // restore other state to normal
4460         //R_Shadow_RenderMode_End();
4461 }
4462
4463 void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
4464 {
4465         float zdist;
4466         vec3_t centerorigin;
4467         float vertex3f[12];
4468         // if it's too close, skip it
4469         if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
4470                 return;
4471         zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
4472         if (zdist < 32)
4473                 return;
4474         if (usequery && r_numqueries + 2 <= r_maxqueries)
4475         {
4476                 rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
4477                 rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
4478                 // we count potential samples in the middle of the screen, we count actual samples at the light location, this allows counting potential samples of off-screen lights
4479                 VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
4480
4481                 CHECKGLERROR
4482                 // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use qglDepthFunc instead
4483                 qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
4484                 qglDepthFunc(GL_ALWAYS);
4485                 R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
4486                 R_Mesh_VertexPointer(vertex3f, 0, 0);
4487                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4488                 qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
4489                 qglDepthFunc(GL_LEQUAL);
4490                 qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
4491                 R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
4492                 R_Mesh_VertexPointer(vertex3f, 0, 0);
4493                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4494                 qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
4495                 CHECKGLERROR
4496         }
4497         rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
4498 }
4499
4500 static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4501
4502 void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
4503 {
4504         vec3_t color;
4505         GLint allpixels = 0, visiblepixels = 0;
4506         // now we have to check the query result
4507         if (rtlight->corona_queryindex_visiblepixels)
4508         {
4509                 CHECKGLERROR
4510                 qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
4511                 qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
4512                 CHECKGLERROR
4513                 //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
4514                 if (visiblepixels < 1 || allpixels < 1)
4515                         return;
4516                 rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
4517                 cscale *= rtlight->corona_visibility;
4518         }
4519         else
4520         {
4521                 // FIXME: these traces should scan all render entities instead of cl.world
4522                 if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
4523                         return;
4524         }
4525         VectorScale(rtlight->currentcolor, cscale, color);
4526         if (VectorLength(color) > (1.0f / 256.0f))
4527         {
4528                 float vertex3f[12];
4529                 qboolean negated = (color[0] + color[1] + color[2] < 0) && vid.support.ext_blend_subtract;
4530                 if(negated)
4531                 {
4532                         VectorNegate(color, color);
4533                         qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4534                 }
4535                 R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
4536                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
4537                 R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
4538                 if(negated)
4539                         qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4540         }
4541 }
4542
4543 void R_Shadow_DrawCoronas(void)
4544 {
4545         int i, flag;
4546         qboolean usequery;
4547         size_t lightindex;
4548         dlight_t *light;
4549         rtlight_t *rtlight;
4550         size_t range;
4551         if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
4552                 return;
4553         if (r_waterstate.renderingscene)
4554                 return;
4555         flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
4556         R_EntityMatrix(&identitymatrix);
4557
4558         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4559
4560         // check occlusion of coronas
4561         // use GL_ARB_occlusion_query if available
4562         // otherwise use raytraces
4563         r_numqueries = 0;
4564         usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
4565         if (usequery)
4566         {
4567                 GL_ColorMask(0,0,0,0);
4568                 if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
4569                 if (r_maxqueries < MAX_OCCLUSION_QUERIES)
4570                 {
4571                         i = r_maxqueries;
4572                         r_maxqueries = (range + r_refdef.scene.numlights) * 4;
4573                         r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
4574                         CHECKGLERROR
4575                         qglGenQueriesARB(r_maxqueries - i, r_queries + i);
4576                         CHECKGLERROR
4577                 }
4578                 RSurf_ActiveWorldEntity();
4579                 GL_BlendFunc(GL_ONE, GL_ZERO);
4580                 GL_CullFace(GL_NONE);
4581                 GL_DepthMask(false);
4582                 GL_DepthRange(0, 1);
4583                 GL_PolygonOffset(0, 0);
4584                 GL_DepthTest(true);
4585                 R_Mesh_ColorPointer(NULL, 0, 0);
4586                 R_Mesh_ResetTextureState();
4587                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
4588         }
4589         for (lightindex = 0;lightindex < range;lightindex++)
4590         {
4591                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4592                 if (!light)
4593                         continue;
4594                 rtlight = &light->rtlight;
4595                 rtlight->corona_visibility = 0;
4596                 rtlight->corona_queryindex_visiblepixels = 0;
4597                 rtlight->corona_queryindex_allpixels = 0;
4598                 if (!(rtlight->flags & flag))
4599                         continue;
4600                 if (rtlight->corona <= 0)
4601                         continue;
4602                 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex)
4603                         continue;
4604                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
4605         }
4606         for (i = 0;i < r_refdef.scene.numlights;i++)
4607         {
4608                 rtlight = r_refdef.scene.lights[i];
4609                 rtlight->corona_visibility = 0;
4610                 rtlight->corona_queryindex_visiblepixels = 0;
4611                 rtlight->corona_queryindex_allpixels = 0;
4612                 if (!(rtlight->flags & flag))
4613                         continue;
4614                 if (rtlight->corona <= 0)
4615                         continue;
4616                 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
4617         }
4618         if (usequery)
4619                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4620
4621         // now draw the coronas using the query data for intensity info
4622         for (lightindex = 0;lightindex < range;lightindex++)
4623         {
4624                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4625                 if (!light)
4626                         continue;
4627                 rtlight = &light->rtlight;
4628                 if (rtlight->corona_visibility <= 0)
4629                         continue;
4630                 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
4631         }
4632         for (i = 0;i < r_refdef.scene.numlights;i++)
4633         {
4634                 rtlight = r_refdef.scene.lights[i];
4635                 if (rtlight->corona_visibility <= 0)
4636                         continue;
4637                 if (gl_flashblend.integer)
4638                         R_DrawCorona(rtlight, rtlight->corona, rtlight->radius * rtlight->coronasizescale * 2.0f);
4639                 else
4640                         R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
4641         }
4642 }
4643
4644
4645
4646 dlight_t *R_Shadow_NewWorldLight(void)
4647 {
4648         return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
4649 }
4650
4651 void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
4652 {
4653         matrix4x4_t matrix;
4654         // validate parameters
4655         if (style < 0 || style >= MAX_LIGHTSTYLES)
4656         {
4657                 Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", light->style, MAX_LIGHTSTYLES);
4658                 style = 0;
4659         }
4660         if (!cubemapname)
4661                 cubemapname = "";
4662
4663         // copy to light properties
4664         VectorCopy(origin, light->origin);
4665         light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
4666         light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
4667         light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
4668         /*
4669         light->color[0] = max(color[0], 0);
4670         light->color[1] = max(color[1], 0);
4671         light->color[2] = max(color[2], 0);
4672         */
4673         light->color[0] = color[0];
4674         light->color[1] = color[1];
4675         light->color[2] = color[2];
4676         light->radius = max(radius, 0);
4677         light->style = style;
4678         light->shadow = shadowenable;
4679         light->corona = corona;
4680         strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
4681         light->coronasizescale = coronasizescale;
4682         light->ambientscale = ambientscale;
4683         light->diffusescale = diffusescale;
4684         light->specularscale = specularscale;
4685         light->flags = flags;
4686
4687         // update renderable light data
4688         Matrix4x4_CreateFromQuakeEntity(&matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], light->radius);
4689         R_RTLight_Update(&light->rtlight, true, &matrix, light->color, light->style, light->cubemapname[0] ? light->cubemapname : NULL, light->shadow, light->corona, light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
4690 }
4691
4692 void R_Shadow_FreeWorldLight(dlight_t *light)
4693 {
4694         if (r_shadow_selectedlight == light)
4695                 r_shadow_selectedlight = NULL;
4696         R_RTLight_Uncompile(&light->rtlight);
4697         Mem_ExpandableArray_FreeRecord(&r_shadow_worldlightsarray, light);
4698 }
4699
4700 void R_Shadow_ClearWorldLights(void)
4701 {
4702         size_t lightindex;
4703         dlight_t *light;
4704         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4705         for (lightindex = 0;lightindex < range;lightindex++)
4706         {
4707                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4708                 if (light)
4709                         R_Shadow_FreeWorldLight(light);
4710         }
4711         r_shadow_selectedlight = NULL;
4712 }
4713
4714 void R_Shadow_SelectLight(dlight_t *light)
4715 {
4716         if (r_shadow_selectedlight)
4717                 r_shadow_selectedlight->selected = false;
4718         r_shadow_selectedlight = light;
4719         if (r_shadow_selectedlight)
4720                 r_shadow_selectedlight->selected = true;
4721 }
4722
4723 void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4724 {
4725         // this is never batched (there can be only one)
4726         float vertex3f[12];
4727         R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
4728         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
4729         R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
4730 }
4731
4732 void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4733 {
4734         float intensity;
4735         float s;
4736         vec3_t spritecolor;
4737         skinframe_t *skinframe;
4738         float vertex3f[12];
4739
4740         // this is never batched (due to the ent parameter changing every time)
4741         // so numsurfaces == 1 and surfacelist[0] == lightnumber
4742         const dlight_t *light = (dlight_t *)ent;
4743         s = EDLIGHTSPRSIZE;
4744
4745         R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
4746
4747         intensity = 0.5f;
4748         VectorScale(light->color, intensity, spritecolor);
4749         if (VectorLength(spritecolor) < 0.1732f)
4750                 VectorSet(spritecolor, 0.1f, 0.1f, 0.1f);
4751         if (VectorLength(spritecolor) > 1.0f)
4752                 VectorNormalize(spritecolor);
4753
4754         // draw light sprite
4755         if (light->cubemapname[0] && !light->shadow)
4756                 skinframe = r_editlights_sprcubemapnoshadowlight;
4757         else if (light->cubemapname[0])
4758                 skinframe = r_editlights_sprcubemaplight;
4759         else if (!light->shadow)
4760                 skinframe = r_editlights_sprnoshadowlight;
4761         else
4762                 skinframe = r_editlights_sprlight;
4763
4764         RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, spritecolor[0], spritecolor[1], spritecolor[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
4765         R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
4766
4767         // draw selection sprite if light is selected
4768         if (light->selected)
4769         {
4770                 RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
4771                 R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
4772                 // VorteX todo: add normalmode/realtime mode light overlay sprites?
4773         }
4774 }
4775
4776 void R_Shadow_DrawLightSprites(void)
4777 {
4778         size_t lightindex;
4779         dlight_t *light;
4780         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4781         for (lightindex = 0;lightindex < range;lightindex++)
4782         {
4783                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4784                 if (light)
4785                         R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
4786         }
4787         R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
4788 }
4789
4790 int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
4791 {
4792         unsigned int range;
4793         dlight_t *light;
4794         rtlight_t *rtlight;
4795         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
4796         if (lightindex >= range)
4797                 return -1;
4798         light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4799         if (!light)
4800                 return 0;
4801         rtlight = &light->rtlight;
4802         //if (!(rtlight->flags & flag))
4803         //      return 0;
4804         VectorCopy(rtlight->shadoworigin, origin);
4805         *radius = rtlight->radius;
4806         VectorCopy(rtlight->color, color);
4807         return 1;
4808 }
4809
4810 void R_Shadow_SelectLightInView(void)
4811 {
4812         float bestrating, rating, temp[3];
4813         dlight_t *best;
4814         size_t lightindex;
4815         dlight_t *light;
4816         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
4817         best = NULL;
4818         bestrating = 0;
4819         for (lightindex = 0;lightindex < range;lightindex++)
4820         {
4821                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4822                 if (!light)
4823                         continue;
4824                 VectorSubtract(light->origin, r_refdef.view.origin, temp);
4825                 rating = (DotProduct(temp, r_refdef.view.forward) / sqrt(DotProduct(temp, temp)));
4826                 if (rating >= 0.95)
4827                 {
4828                         rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
4829                         if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1.0f)
4830                         {
4831                                 bestrating = rating;
4832                                 best = light;
4833                         }
4834                 }
4835         }
4836         R_Shadow_SelectLight(best);
4837 }
4838
4839 void R_Shadow_LoadWorldLights(void)
4840 {
4841         int n, a, style, shadow, flags;
4842         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
4843         float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
4844         if (cl.worldmodel == NULL)
4845         {
4846                 Con_Print("No map loaded.\n");
4847                 return;
4848         }
4849         FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
4850         strlcat (name, ".rtlights", sizeof (name));
4851         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
4852         if (lightsstring)
4853         {
4854                 s = lightsstring;
4855                 n = 0;
4856                 while (*s)
4857                 {
4858                         t = s;
4859                         /*
4860                         shadow = true;
4861                         for (;COM_Parse(t, true) && strcmp(
4862                         if (COM_Parse(t, true))
4863                         {
4864                                 if (com_token[0] == '!')
4865                                 {
4866                                         shadow = false;
4867                                         origin[0] = atof(com_token+1);
4868                                 }
4869                                 else
4870                                         origin[0] = atof(com_token);
4871                                 if (Com_Parse(t
4872                         }
4873                         */
4874                         t = s;
4875                         while (*s && *s != '\n' && *s != '\r')
4876                                 s++;
4877                         if (!*s)
4878                                 break;
4879                         tempchar = *s;
4880                         shadow = true;
4881                         // check for modifier flags
4882                         if (*t == '!')
4883                         {
4884                                 shadow = false;
4885                                 t++;
4886                         }
4887                         *s = 0;
4888 #if _MSC_VER >= 1400
4889 #define sscanf sscanf_s
4890 #endif
4891                         cubemapname[sizeof(cubemapname)-1] = 0;
4892 #if MAX_QPATH != 128
4893 #error update this code if MAX_QPATH changes
4894 #endif
4895                         a = sscanf(t, "%f %f %f %f %f %f %f %d %127s %f %f %f %f %f %f %f %f %i", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname
4896 #if _MSC_VER >= 1400
4897 , sizeof(cubemapname)
4898 #endif
4899 , &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
4900                         *s = tempchar;
4901                         if (a < 18)
4902                                 flags = LIGHTFLAG_REALTIMEMODE;
4903                         if (a < 17)
4904                                 specularscale = 1;
4905                         if (a < 16)
4906                                 diffusescale = 1;
4907                         if (a < 15)
4908                                 ambientscale = 0;
4909                         if (a < 14)
4910                                 coronasizescale = 0.25f;
4911                         if (a < 13)
4912                                 VectorClear(angles);
4913                         if (a < 10)
4914                                 corona = 0;
4915                         if (a < 9 || !strcmp(cubemapname, "\"\""))
4916                                 cubemapname[0] = 0;
4917                         // remove quotes on cubemapname
4918                         if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
4919                         {
4920                                 size_t namelen;
4921                                 namelen = strlen(cubemapname) - 2;
4922                                 memmove(cubemapname, cubemapname + 1, namelen);
4923                                 cubemapname[namelen] = '\0';
4924                         }
4925                         if (a < 8)
4926                         {
4927                                 Con_Printf("found %d parameters on line %i, should be 8 or more parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style \"cubemapname\" corona angles[0] angles[1] angles[2] coronasizescale ambientscale diffusescale specularscale flags)\n", a, n + 1);
4928                                 break;
4929                         }
4930                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
4931                         if (*s == '\r')
4932                                 s++;
4933                         if (*s == '\n')
4934                                 s++;
4935                         n++;
4936                 }
4937                 if (*s)
4938                         Con_Printf("invalid rtlights file \"%s\"\n", name);
4939                 Mem_Free(lightsstring);
4940         }
4941 }
4942
4943 void R_Shadow_SaveWorldLights(void)
4944 {
4945         size_t lightindex;
4946         dlight_t *light;
4947         size_t bufchars, bufmaxchars;
4948         char *buf, *oldbuf;
4949         char name[MAX_QPATH];
4950         char line[MAX_INPUTLINE];
4951         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
4952         // I hate lines which are 3 times my screen size :( --blub
4953         if (!range)
4954                 return;
4955         if (cl.worldmodel == NULL)
4956         {
4957                 Con_Print("No map loaded.\n");
4958                 return;
4959         }
4960         FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
4961         strlcat (name, ".rtlights", sizeof (name));
4962         bufchars = bufmaxchars = 0;
4963         buf = NULL;
4964         for (lightindex = 0;lightindex < range;lightindex++)
4965         {
4966                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
4967                 if (!light)
4968                         continue;
4969                 if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE)
4970                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f %f %f %f %f %i\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2], light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
4971                 else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
4972                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2]);
4973                 else
4974                         dpsnprintf(line, sizeof(line), "%s%f %f %f %f %f %f %f %d\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style);
4975                 if (bufchars + strlen(line) > bufmaxchars)
4976                 {
4977                         bufmaxchars = bufchars + strlen(line) + 2048;
4978                         oldbuf = buf;
4979                         buf = (char *)Mem_Alloc(tempmempool, bufmaxchars);
4980                         if (oldbuf)
4981                         {
4982                                 if (bufchars)
4983                                         memcpy(buf, oldbuf, bufchars);
4984                                 Mem_Free(oldbuf);
4985                         }
4986                 }
4987                 if (strlen(line))
4988                 {
4989                         memcpy(buf + bufchars, line, strlen(line));
4990                         bufchars += strlen(line);
4991                 }
4992         }
4993         if (bufchars)
4994                 FS_WriteFile(name, buf, (fs_offset_t)bufchars);
4995         if (buf)
4996                 Mem_Free(buf);
4997 }
4998
4999 void R_Shadow_LoadLightsFile(void)
5000 {
5001         int n, a, style;
5002         char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
5003         float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
5004         if (cl.worldmodel == NULL)
5005         {
5006                 Con_Print("No map loaded.\n");
5007                 return;
5008         }
5009         FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
5010         strlcat (name, ".lights", sizeof (name));
5011         lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
5012         if (lightsstring)
5013         {
5014                 s = lightsstring;
5015                 n = 0;
5016                 while (*s)
5017                 {
5018                         t = s;
5019                         while (*s && *s != '\n' && *s != '\r')
5020                                 s++;
5021                         if (!*s)
5022                                 break;
5023                         tempchar = *s;
5024                         *s = 0;
5025                         a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &origin[0], &origin[1], &origin[2], &falloff, &color[0], &color[1], &color[2], &subtract, &spotdir[0], &spotdir[1], &spotdir[2], &spotcone, &distbias, &style);
5026                         *s = tempchar;
5027                         if (a < 14)
5028                         {
5029                                 Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
5030                                 break;
5031                         }
5032                         radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f));
5033                         radius = bound(15, radius, 4096);
5034                         VectorScale(color, (2.0f / (8388608.0f)), color);
5035                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
5036                         if (*s == '\r')
5037                                 s++;
5038                         if (*s == '\n')
5039                                 s++;
5040                         n++;
5041                 }
5042                 if (*s)
5043                         Con_Printf("invalid lights file \"%s\"\n", name);
5044                 Mem_Free(lightsstring);
5045         }
5046 }
5047
5048 // tyrlite/hmap2 light types in the delay field
5049 typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
5050
5051 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
5052 {
5053         int entnum;
5054         int style;
5055         int islight;
5056         int skin;
5057         int pflags;
5058         //int effects;
5059         int type;
5060         int n;
5061         char *entfiledata;
5062         const char *data;
5063         float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
5064         char key[256], value[MAX_INPUTLINE];
5065
5066         if (cl.worldmodel == NULL)
5067         {
5068                 Con_Print("No map loaded.\n");
5069                 return;
5070         }
5071         // try to load a .ent file first
5072         FS_StripExtension (cl.worldmodel->name, key, sizeof (key));
5073         strlcat (key, ".ent", sizeof (key));
5074         data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL);
5075         // and if that is not found, fall back to the bsp file entity string
5076         if (!data)
5077                 data = cl.worldmodel->brush.entities;
5078         if (!data)
5079                 return;
5080         for (entnum = 0;COM_ParseToken_Simple(&data, false, false) && com_token[0] == '{';entnum++)
5081         {
5082                 type = LIGHTTYPE_MINUSX;
5083                 origin[0] = origin[1] = origin[2] = 0;
5084                 originhack[0] = originhack[1] = originhack[2] = 0;
5085                 angles[0] = angles[1] = angles[2] = 0;
5086                 color[0] = color[1] = color[2] = 1;
5087                 light[0] = light[1] = light[2] = 1;light[3] = 300;
5088                 overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
5089                 fadescale = 1;
5090                 lightscale = 1;
5091                 style = 0;
5092                 skin = 0;
5093                 pflags = 0;
5094                 //effects = 0;
5095                 islight = false;
5096                 while (1)
5097                 {
5098                         if (!COM_ParseToken_Simple(&data, false, false))
5099                                 break; // error
5100                         if (com_token[0] == '}')
5101                                 break; // end of entity
5102                         if (com_token[0] == '_')
5103                                 strlcpy(key, com_token + 1, sizeof(key));
5104                         else
5105                                 strlcpy(key, com_token, sizeof(key));
5106                         while (key[strlen(key)-1] == ' ') // remove trailing spaces
5107                                 key[strlen(key)-1] = 0;
5108                         if (!COM_ParseToken_Simple(&data, false, false))
5109                                 break; // error
5110                         strlcpy(value, com_token, sizeof(value));
5111
5112                         // now that we have the key pair worked out...
5113                         if (!strcmp("light", key))
5114                         {
5115                                 n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
5116                                 if (n == 1)
5117                                 {
5118                                         // quake
5119                                         light[0] = vec[0] * (1.0f / 256.0f);
5120                                         light[1] = vec[0] * (1.0f / 256.0f);
5121                                         light[2] = vec[0] * (1.0f / 256.0f);
5122                                         light[3] = vec[0];
5123                                 }
5124                                 else if (n == 4)
5125                                 {
5126                                         // halflife
5127                                         light[0] = vec[0] * (1.0f / 255.0f);
5128                                         light[1] = vec[1] * (1.0f / 255.0f);
5129                                         light[2] = vec[2] * (1.0f / 255.0f);
5130                                         light[3] = vec[3];
5131                                 }
5132                         }
5133                         else if (!strcmp("delay", key))
5134                                 type = atoi(value);
5135                         else if (!strcmp("origin", key))
5136                                 sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
5137                         else if (!strcmp("angle", key))
5138                                 angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
5139                         else if (!strcmp("angles", key))
5140                                 sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
5141                         else if (!strcmp("color", key))
5142                                 sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
5143                         else if (!strcmp("wait", key))
5144                                 fadescale = atof(value);
5145                         else if (!strcmp("classname", key))
5146                         {
5147                                 if (!strncmp(value, "light", 5))
5148                                 {
5149                                         islight = true;
5150                                         if (!strcmp(value, "light_fluoro"))
5151                                         {
5152                                                 originhack[0] = 0;
5153                                                 originhack[1] = 0;
5154                                                 originhack[2] = 0;
5155                                                 overridecolor[0] = 1;
5156                                                 overridecolor[1] = 1;
5157                                                 overridecolor[2] = 1;
5158                                         }
5159                                         if (!strcmp(value, "light_fluorospark"))
5160                                         {
5161                                                 originhack[0] = 0;
5162                                                 originhack[1] = 0;
5163                                                 originhack[2] = 0;
5164                                                 overridecolor[0] = 1;
5165                                                 overridecolor[1] = 1;
5166                                                 overridecolor[2] = 1;
5167                                         }
5168                                         if (!strcmp(value, "light_globe"))
5169                                         {
5170                                                 originhack[0] = 0;
5171                                                 originhack[1] = 0;
5172                                                 originhack[2] = 0;
5173                                                 overridecolor[0] = 1;
5174                                                 overridecolor[1] = 0.8;
5175                                                 overridecolor[2] = 0.4;
5176                                         }
5177                                         if (!strcmp(value, "light_flame_large_yellow"))
5178                                         {
5179                                                 originhack[0] = 0;
5180                                                 originhack[1] = 0;
5181                                                 originhack[2] = 0;
5182                                                 overridecolor[0] = 1;
5183                                                 overridecolor[1] = 0.5;
5184                                                 overridecolor[2] = 0.1;
5185                                         }
5186                                         if (!strcmp(value, "light_flame_small_yellow"))
5187                                         {
5188                                                 originhack[0] = 0;
5189                                                 originhack[1] = 0;
5190                                                 originhack[2] = 0;
5191                                                 overridecolor[0] = 1;
5192                                                 overridecolor[1] = 0.5;
5193                                                 overridecolor[2] = 0.1;
5194                                         }
5195                                         if (!strcmp(value, "light_torch_small_white"))
5196                                         {
5197                                                 originhack[0] = 0;
5198                                                 originhack[1] = 0;
5199                                                 originhack[2] = 0;
5200                                                 overridecolor[0] = 1;
5201                                                 overridecolor[1] = 0.5;
5202                                                 overridecolor[2] = 0.1;
5203                                         }
5204                                         if (!strcmp(value, "light_torch_small_walltorch"))
5205                                         {
5206                                                 originhack[0] = 0;
5207                                                 originhack[1] = 0;
5208                                                 originhack[2] = 0;
5209                                                 overridecolor[0] = 1;
5210                                                 overridecolor[1] = 0.5;
5211                                                 overridecolor[2] = 0.1;
5212                                         }
5213                                 }
5214                         }
5215                         else if (!strcmp("style", key))
5216                                 style = atoi(value);
5217                         else if (!strcmp("skin", key))
5218                                 skin = (int)atof(value);
5219                         else if (!strcmp("pflags", key))
5220                                 pflags = (int)atof(value);
5221                         //else if (!strcmp("effects", key))
5222                         //      effects = (int)atof(value);
5223                         else if (cl.worldmodel->type == mod_brushq3)
5224                         {
5225                                 if (!strcmp("scale", key))
5226                                         lightscale = atof(value);
5227                                 if (!strcmp("fade", key))
5228                                         fadescale = atof(value);
5229                         }
5230                 }
5231                 if (!islight)
5232                         continue;
5233                 if (lightscale <= 0)
5234                         lightscale = 1;
5235                 if (fadescale <= 0)
5236                         fadescale = 1;
5237                 if (color[0] == color[1] && color[0] == color[2])
5238                 {
5239                         color[0] *= overridecolor[0];
5240                         color[1] *= overridecolor[1];
5241                         color[2] *= overridecolor[2];
5242                 }
5243                 radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
5244                 color[0] = color[0] * light[0];
5245                 color[1] = color[1] * light[1];
5246                 color[2] = color[2] * light[2];
5247                 switch (type)
5248                 {
5249                 case LIGHTTYPE_MINUSX:
5250                         break;
5251                 case LIGHTTYPE_RECIPX:
5252                         radius *= 2;
5253                         VectorScale(color, (1.0f / 16.0f), color);
5254                         break;
5255                 case LIGHTTYPE_RECIPXX:
5256                         radius *= 2;
5257                         VectorScale(color, (1.0f / 16.0f), color);
5258                         break;
5259                 default:
5260                 case LIGHTTYPE_NONE:
5261                         break;
5262                 case LIGHTTYPE_SUN:
5263                         break;
5264                 case LIGHTTYPE_MINUSXX:
5265                         break;
5266                 }
5267                 VectorAdd(origin, originhack, origin);
5268                 if (radius >= 1)
5269                         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
5270         }
5271         if (entfiledata)
5272                 Mem_Free(entfiledata);
5273 }
5274
5275
5276 void R_Shadow_SetCursorLocationForView(void)
5277 {
5278         vec_t dist, push;
5279         vec3_t dest, endpos;
5280         trace_t trace;
5281         VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
5282         trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
5283         if (trace.fraction < 1)
5284         {
5285                 dist = trace.fraction * r_editlights_cursordistance.value;
5286                 push = r_editlights_cursorpushback.value;
5287                 if (push > dist)
5288                         push = dist;
5289                 push = -push;
5290                 VectorMA(trace.endpos, push, r_refdef.view.forward, endpos);
5291                 VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
5292         }
5293         else
5294         {
5295                 VectorClear( endpos );
5296         }
5297         r_editlights_cursorlocation[0] = floor(endpos[0] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
5298         r_editlights_cursorlocation[1] = floor(endpos[1] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
5299         r_editlights_cursorlocation[2] = floor(endpos[2] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
5300 }
5301
5302 void R_Shadow_UpdateWorldLightSelection(void)
5303 {
5304         if (r_editlights.integer)
5305         {
5306                 R_Shadow_SetCursorLocationForView();
5307                 R_Shadow_SelectLightInView();
5308         }
5309         else
5310                 R_Shadow_SelectLight(NULL);
5311 }
5312
5313 void R_Shadow_EditLights_Clear_f(void)
5314 {
5315         R_Shadow_ClearWorldLights();
5316 }
5317
5318 void R_Shadow_EditLights_Reload_f(void)
5319 {
5320         if (!cl.worldmodel)
5321                 return;
5322         strlcpy(r_shadow_mapname, cl.worldmodel->name, sizeof(r_shadow_mapname));
5323         R_Shadow_ClearWorldLights();
5324         R_Shadow_LoadWorldLights();
5325         if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
5326         {
5327                 R_Shadow_LoadLightsFile();
5328                 if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
5329                         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
5330         }
5331 }
5332
5333 void R_Shadow_EditLights_Save_f(void)
5334 {
5335         if (!cl.worldmodel)
5336                 return;
5337         R_Shadow_SaveWorldLights();
5338 }
5339
5340 void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
5341 {
5342         R_Shadow_ClearWorldLights();
5343         R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
5344 }
5345
5346 void R_Shadow_EditLights_ImportLightsFile_f(void)
5347 {
5348         R_Shadow_ClearWorldLights();
5349         R_Shadow_LoadLightsFile();
5350 }
5351
5352 void R_Shadow_EditLights_Spawn_f(void)
5353 {
5354         vec3_t color;
5355         if (!r_editlights.integer)
5356         {
5357                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
5358                 return;
5359         }
5360         if (Cmd_Argc() != 1)
5361         {
5362                 Con_Print("r_editlights_spawn does not take parameters\n");
5363                 return;
5364         }
5365         color[0] = color[1] = color[2] = 1;
5366         R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
5367 }
5368
5369 void R_Shadow_EditLights_Edit_f(void)
5370 {
5371         vec3_t origin, angles, color;
5372         vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
5373         int style, shadows, flags, normalmode, realtimemode;
5374         char cubemapname[MAX_INPUTLINE];
5375         if (!r_editlights.integer)
5376         {
5377                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
5378                 return;
5379         }
5380         if (!r_shadow_selectedlight)
5381         {
5382                 Con_Print("No selected light.\n");
5383                 return;
5384         }
5385         VectorCopy(r_shadow_selectedlight->origin, origin);
5386         VectorCopy(r_shadow_selectedlight->angles, angles);
5387         VectorCopy(r_shadow_selectedlight->color, color);
5388         radius = r_shadow_selectedlight->radius;
5389         style = r_shadow_selectedlight->style;
5390         if (r_shadow_selectedlight->cubemapname)
5391                 strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
5392         else
5393                 cubemapname[0] = 0;
5394         shadows = r_shadow_selectedlight->shadow;
5395         corona = r_shadow_selectedlight->corona;
5396         coronasizescale = r_shadow_selectedlight->coronasizescale;
5397         ambientscale = r_shadow_selectedlight->ambientscale;
5398         diffusescale = r_shadow_selectedlight->diffusescale;
5399         specularscale = r_shadow_selectedlight->specularscale;
5400         flags = r_shadow_selectedlight->flags;
5401         normalmode = (flags & LIGHTFLAG_NORMALMODE) != 0;
5402         realtimemode = (flags & LIGHTFLAG_REALTIMEMODE) != 0;
5403         if (!strcmp(Cmd_Argv(1), "origin"))
5404         {
5405                 if (Cmd_Argc() != 5)
5406                 {
5407                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
5408                         return;
5409                 }
5410                 origin[0] = atof(Cmd_Argv(2));
5411                 origin[1] = atof(Cmd_Argv(3));
5412                 origin[2] = atof(Cmd_Argv(4));
5413         }
5414         else if (!strcmp(Cmd_Argv(1), "originx"))
5415         {
5416                 if (Cmd_Argc() != 3)
5417                 {
5418                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5419                         return;
5420                 }
5421                 origin[0] = atof(Cmd_Argv(2));
5422         }
5423         else if (!strcmp(Cmd_Argv(1), "originy"))
5424         {
5425                 if (Cmd_Argc() != 3)
5426                 {
5427                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5428                         return;
5429                 }
5430                 origin[1] = atof(Cmd_Argv(2));
5431         }
5432         else if (!strcmp(Cmd_Argv(1), "originz"))
5433         {
5434                 if (Cmd_Argc() != 3)
5435                 {
5436                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5437                         return;
5438                 }
5439                 origin[2] = atof(Cmd_Argv(2));
5440         }
5441         else if (!strcmp(Cmd_Argv(1), "move"))
5442         {
5443                 if (Cmd_Argc() != 5)
5444                 {
5445                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
5446                         return;
5447                 }
5448                 origin[0] += atof(Cmd_Argv(2));
5449                 origin[1] += atof(Cmd_Argv(3));
5450                 origin[2] += atof(Cmd_Argv(4));
5451         }
5452         else if (!strcmp(Cmd_Argv(1), "movex"))
5453         {
5454                 if (Cmd_Argc() != 3)
5455                 {
5456                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5457                         return;
5458                 }
5459                 origin[0] += atof(Cmd_Argv(2));
5460         }
5461         else if (!strcmp(Cmd_Argv(1), "movey"))
5462         {
5463                 if (Cmd_Argc() != 3)
5464                 {
5465                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5466                         return;
5467                 }
5468                 origin[1] += atof(Cmd_Argv(2));
5469         }
5470         else if (!strcmp(Cmd_Argv(1), "movez"))
5471         {
5472                 if (Cmd_Argc() != 3)
5473                 {
5474                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5475                         return;
5476                 }
5477                 origin[2] += atof(Cmd_Argv(2));
5478         }
5479         else if (!strcmp(Cmd_Argv(1), "angles"))
5480         {
5481                 if (Cmd_Argc() != 5)
5482                 {
5483                         Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(1));
5484                         return;
5485                 }
5486                 angles[0] = atof(Cmd_Argv(2));
5487                 angles[1] = atof(Cmd_Argv(3));
5488                 angles[2] = atof(Cmd_Argv(4));
5489         }
5490         else if (!strcmp(Cmd_Argv(1), "anglesx"))
5491         {
5492                 if (Cmd_Argc() != 3)
5493                 {
5494                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5495                         return;
5496                 }
5497                 angles[0] = atof(Cmd_Argv(2));
5498         }
5499         else if (!strcmp(Cmd_Argv(1), "anglesy"))
5500         {
5501                 if (Cmd_Argc() != 3)
5502                 {
5503                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5504                         return;
5505                 }
5506                 angles[1] = atof(Cmd_Argv(2));
5507         }
5508         else if (!strcmp(Cmd_Argv(1), "anglesz"))
5509         {
5510                 if (Cmd_Argc() != 3)
5511                 {
5512                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5513                         return;
5514                 }
5515                 angles[2] = atof(Cmd_Argv(2));
5516         }
5517         else if (!strcmp(Cmd_Argv(1), "color"))
5518         {
5519                 if (Cmd_Argc() != 5)
5520                 {
5521                         Con_Printf("usage: r_editlights_edit %s red green blue\n", Cmd_Argv(1));
5522                         return;
5523                 }
5524                 color[0] = atof(Cmd_Argv(2));
5525                 color[1] = atof(Cmd_Argv(3));
5526                 color[2] = atof(Cmd_Argv(4));
5527         }
5528         else if (!strcmp(Cmd_Argv(1), "radius"))
5529         {
5530                 if (Cmd_Argc() != 3)
5531                 {
5532                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5533                         return;
5534                 }
5535                 radius = atof(Cmd_Argv(2));
5536         }
5537         else if (!strcmp(Cmd_Argv(1), "colorscale"))
5538         {
5539                 if (Cmd_Argc() == 3)
5540                 {
5541                         double scale = atof(Cmd_Argv(2));
5542                         color[0] *= scale;
5543                         color[1] *= scale;
5544                         color[2] *= scale;
5545                 }
5546                 else
5547                 {
5548                         if (Cmd_Argc() != 5)
5549                         {
5550                                 Con_Printf("usage: r_editlights_edit %s red green blue  (OR grey instead of red green blue)\n", Cmd_Argv(1));
5551                                 return;
5552                         }
5553                         color[0] *= atof(Cmd_Argv(2));
5554                         color[1] *= atof(Cmd_Argv(3));
5555                         color[2] *= atof(Cmd_Argv(4));
5556                 }
5557         }
5558         else if (!strcmp(Cmd_Argv(1), "radiusscale") || !strcmp(Cmd_Argv(1), "sizescale"))
5559         {
5560                 if (Cmd_Argc() != 3)
5561                 {
5562                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5563                         return;
5564                 }
5565                 radius *= atof(Cmd_Argv(2));
5566         }
5567         else if (!strcmp(Cmd_Argv(1), "style"))
5568         {
5569                 if (Cmd_Argc() != 3)
5570                 {
5571                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5572                         return;
5573                 }
5574                 style = atoi(Cmd_Argv(2));
5575         }
5576         else if (!strcmp(Cmd_Argv(1), "cubemap"))
5577         {
5578                 if (Cmd_Argc() > 3)
5579                 {
5580                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5581                         return;
5582                 }
5583                 if (Cmd_Argc() == 3)
5584                         strlcpy(cubemapname, Cmd_Argv(2), sizeof(cubemapname));
5585                 else
5586                         cubemapname[0] = 0;
5587         }
5588         else if (!strcmp(Cmd_Argv(1), "shadows"))
5589         {
5590                 if (Cmd_Argc() != 3)
5591                 {
5592                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5593                         return;
5594                 }
5595                 shadows = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
5596         }
5597         else if (!strcmp(Cmd_Argv(1), "corona"))
5598         {
5599                 if (Cmd_Argc() != 3)
5600                 {
5601                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5602                         return;
5603                 }
5604                 corona = atof(Cmd_Argv(2));
5605         }
5606         else if (!strcmp(Cmd_Argv(1), "coronasize"))
5607         {
5608                 if (Cmd_Argc() != 3)
5609                 {
5610                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5611                         return;
5612                 }
5613                 coronasizescale = atof(Cmd_Argv(2));
5614         }
5615         else if (!strcmp(Cmd_Argv(1), "ambient"))
5616         {
5617                 if (Cmd_Argc() != 3)
5618                 {
5619                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5620                         return;
5621                 }
5622                 ambientscale = atof(Cmd_Argv(2));
5623         }
5624         else if (!strcmp(Cmd_Argv(1), "diffuse"))
5625         {
5626                 if (Cmd_Argc() != 3)
5627                 {
5628                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5629                         return;
5630                 }
5631                 diffusescale = atof(Cmd_Argv(2));
5632         }
5633         else if (!strcmp(Cmd_Argv(1), "specular"))
5634         {
5635                 if (Cmd_Argc() != 3)
5636                 {
5637                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5638                         return;
5639                 }
5640                 specularscale = atof(Cmd_Argv(2));
5641         }
5642         else if (!strcmp(Cmd_Argv(1), "normalmode"))
5643         {
5644                 if (Cmd_Argc() != 3)
5645                 {
5646                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5647                         return;
5648                 }
5649                 normalmode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
5650         }
5651         else if (!strcmp(Cmd_Argv(1), "realtimemode"))
5652         {
5653                 if (Cmd_Argc() != 3)
5654                 {
5655                         Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(1));
5656                         return;
5657                 }
5658                 realtimemode = Cmd_Argv(2)[0] == 'y' || Cmd_Argv(2)[0] == 'Y' || Cmd_Argv(2)[0] == 't' || atoi(Cmd_Argv(2));
5659         }
5660         else
5661         {
5662                 Con_Print("usage: r_editlights_edit [property] [value]\n");
5663                 Con_Print("Selected light's properties:\n");
5664                 Con_Printf("Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
5665                 Con_Printf("Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
5666                 Con_Printf("Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
5667                 Con_Printf("Radius       : %f\n", r_shadow_selectedlight->radius);
5668                 Con_Printf("Corona       : %f\n", r_shadow_selectedlight->corona);
5669                 Con_Printf("Style        : %i\n", r_shadow_selectedlight->style);
5670                 Con_Printf("Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
5671                 Con_Printf("Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);
5672                 Con_Printf("CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);
5673                 Con_Printf("Ambient      : %f\n", r_shadow_selectedlight->ambientscale);
5674                 Con_Printf("Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);
5675                 Con_Printf("Specular     : %f\n", r_shadow_selectedlight->specularscale);
5676                 Con_Printf("NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");
5677                 Con_Printf("RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");
5678                 return;
5679         }
5680         flags = (normalmode ? LIGHTFLAG_NORMALMODE : 0) | (realtimemode ? LIGHTFLAG_REALTIMEMODE : 0);
5681         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
5682 }
5683
5684 void R_Shadow_EditLights_EditAll_f(void)
5685 {
5686         size_t lightindex;
5687         dlight_t *light;
5688         size_t range;
5689
5690         if (!r_editlights.integer)
5691         {
5692                 Con_Print("Cannot edit lights when not in editing mode. Set r_editlights to 1.\n");
5693                 return;
5694         }
5695
5696         // EditLights doesn't seem to have a "remove" command or something so:
5697         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5698         for (lightindex = 0;lightindex < range;lightindex++)
5699         {
5700                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5701                 if (!light)
5702                         continue;
5703                 R_Shadow_SelectLight(light);
5704                 R_Shadow_EditLights_Edit_f();
5705         }
5706 }
5707
5708 void R_Shadow_EditLights_DrawSelectedLightProperties(void)
5709 {
5710         int lightnumber, lightcount;
5711         size_t lightindex, range;
5712         dlight_t *light;
5713         float x, y;
5714         char temp[256];
5715         if (!r_editlights.integer)
5716                 return;
5717         x = vid_conwidth.value - 240;
5718         y = 5;
5719         DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
5720         lightnumber = -1;
5721         lightcount = 0;
5722         range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
5723         for (lightindex = 0;lightindex < range;lightindex++)
5724         {
5725                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
5726                 if (!light)
5727                         continue;
5728                 if (light == r_shadow_selectedlight)
5729                         lightnumber = lightindex;
5730                 lightcount++;
5731         }
5732         dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
5733         dpsnprintf(temp, sizeof(temp), "Total lights : %i active (%i total)", lightcount, (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
5734         y += 8;
5735         if (r_shadow_selectedlight == NULL)
5736                 return;
5737         dpsnprintf(temp, sizeof(temp), "Light #%i properties:", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5738         dpsnprintf(temp, sizeof(temp), "Origin       : %.0f %.0f %.0f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5739         dpsnprintf(temp, sizeof(temp), "Angles       : %.0f %.0f %.0f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5740         dpsnprintf(temp, sizeof(temp), "Color        : %.2f %.2f %.2f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5741         dpsnprintf(temp, sizeof(temp), "Radius       : %.0f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5742         dpsnprintf(temp, sizeof(temp), "Corona       : %.0f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5743         dpsnprintf(temp, sizeof(temp), "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5744         dpsnprintf(temp, sizeof(temp), "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5745         dpsnprintf(temp, sizeof(temp), "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5746         dpsnprintf(temp, sizeof(temp), "CoronaSize   : %.2f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5747         dpsnprintf(temp, sizeof(temp), "Ambient      : %.2f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5748         dpsnprintf(temp, sizeof(temp), "Diffuse      : %.2f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5749         dpsnprintf(temp, sizeof(temp), "Specular     : %.2f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5750         dpsnprintf(temp, sizeof(temp), "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5751         dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
5752 }
5753
5754 void R_Shadow_EditLights_ToggleShadow_f(void)
5755 {
5756         if (!r_editlights.integer)
5757         {
5758                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
5759                 return;
5760         }
5761         if (!r_shadow_selectedlight)
5762         {
5763                 Con_Print("No selected light.\n");
5764                 return;
5765         }
5766         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
5767 }
5768
5769 void R_Shadow_EditLights_ToggleCorona_f(void)
5770 {
5771         if (!r_editlights.integer)
5772         {
5773                 Con_Print("Cannot spawn light when not in editing mode.  Set r_editlights to 1.\n");
5774                 return;
5775         }
5776         if (!r_shadow_selectedlight)
5777         {
5778                 Con_Print("No selected light.\n");
5779                 return;
5780         }
5781         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
5782 }
5783
5784 void R_Shadow_EditLights_Remove_f(void)
5785 {
5786         if (!r_editlights.integer)
5787         {
5788                 Con_Print("Cannot remove light when not in editing mode.  Set r_editlights to 1.\n");
5789                 return;
5790         }
5791         if (!r_shadow_selectedlight)
5792         {
5793                 Con_Print("No selected light.\n");
5794                 return;
5795         }
5796         R_Shadow_FreeWorldLight(r_shadow_selectedlight);
5797         r_shadow_selectedlight = NULL;
5798 }
5799
5800 void R_Shadow_EditLights_Help_f(void)
5801 {
5802         Con_Print(
5803 "Documentation on r_editlights system:\n"
5804 "Settings:\n"
5805 "r_editlights : enable/disable editing mode\n"
5806 "r_editlights_cursordistance : maximum distance of cursor from eye\n"
5807 "r_editlights_cursorpushback : push back cursor this far from surface\n"
5808 "r_editlights_cursorpushoff : push cursor off surface this far\n"
5809 "r_editlights_cursorgrid : snap cursor to grid of this size\n"
5810 "r_editlights_quakelightsizescale : imported quake light entity size scaling\n"
5811 "Commands:\n"
5812 "r_editlights_help : this help\n"
5813 "r_editlights_clear : remove all lights\n"
5814 "r_editlights_reload : reload .rtlights, .lights file, or entities\n"
5815 "r_editlights_save : save to .rtlights file\n"
5816 "r_editlights_spawn : create a light with default settings\n"
5817 "r_editlights_edit command : edit selected light - more documentation below\n"
5818 "r_editlights_remove : remove selected light\n"
5819 "r_editlights_toggleshadow : toggles on/off selected light's shadow property\n"
5820 "r_editlights_importlightentitiesfrommap : reload light entities\n"
5821 "r_editlights_importlightsfile : reload .light file (produced by hlight)\n"
5822 "Edit commands:\n"
5823 "origin x y z : set light location\n"
5824 "originx x: set x component of light location\n"
5825 "originy y: set y component of light location\n"
5826 "originz z: set z component of light location\n"
5827 "move x y z : adjust light location\n"
5828 "movex x: adjust x component of light location\n"
5829 "movey y: adjust y component of light location\n"
5830 "movez z: adjust z component of light location\n"
5831 "angles x y z : set light angles\n"
5832 "anglesx x: set x component of light angles\n"
5833 "anglesy y: set y component of light angles\n"
5834 "anglesz z: set z component of light angles\n"
5835 "color r g b : set color of light (can be brighter than 1 1 1)\n"
5836 "radius radius : set radius (size) of light\n"
5837 "colorscale grey : multiply color of light (1 does nothing)\n"
5838 "colorscale r g b : multiply color of light (1 1 1 does nothing)\n"
5839 "radiusscale scale : multiply radius (size) of light (1 does nothing)\n"
5840 "sizescale scale : multiply radius (size) of light (1 does nothing)\n"
5841 "style style : set lightstyle of light (flickering patterns, switches, etc)\n"
5842 "cubemap basename : set filter cubemap of light (not yet supported)\n"
5843 "shadows 1/0 : turn on/off shadows\n"
5844 "corona n : set corona intensity\n"
5845 "coronasize n : set corona size (0-1)\n"
5846 "ambient n : set ambient intensity (0-1)\n"
5847 "diffuse n : set diffuse intensity (0-1)\n"
5848 "specular n : set specular intensity (0-1)\n"
5849 "normalmode 1/0 : turn on/off rendering of this light in rtworld 0 mode\n"
5850 "realtimemode 1/0 : turn on/off rendering of this light in rtworld 1 mode\n"
5851 "<nothing> : print light properties to console\n"
5852         );
5853 }
5854
5855 void R_Shadow_EditLights_CopyInfo_f(void)
5856 {
5857         if (!r_editlights.integer)
5858         {
5859                 Con_Print("Cannot copy light info when not in editing mode.  Set r_editlights to 1.\n");
5860                 return;
5861         }
5862         if (!r_shadow_selectedlight)
5863         {
5864                 Con_Print("No selected light.\n");
5865                 return;
5866         }
5867         VectorCopy(r_shadow_selectedlight->angles, r_shadow_bufferlight.angles);
5868         VectorCopy(r_shadow_selectedlight->color, r_shadow_bufferlight.color);
5869         r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
5870         r_shadow_bufferlight.style = r_shadow_selectedlight->style;
5871         if (r_shadow_selectedlight->cubemapname)
5872                 strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
5873         else
5874                 r_shadow_bufferlight.cubemapname[0] = 0;
5875         r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;
5876         r_shadow_bufferlight.corona = r_shadow_selectedlight->corona;
5877         r_shadow_bufferlight.coronasizescale = r_shadow_selectedlight->coronasizescale;
5878         r_shadow_bufferlight.ambientscale = r_shadow_selectedlight->ambientscale;
5879         r_shadow_bufferlight.diffusescale = r_shadow_selectedlight->diffusescale;
5880         r_shadow_bufferlight.specularscale = r_shadow_selectedlight->specularscale;
5881         r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
5882 }
5883
5884 void R_Shadow_EditLights_PasteInfo_f(void)
5885 {
5886         if (!r_editlights.integer)
5887         {
5888                 Con_Print("Cannot paste light info when not in editing mode.  Set r_editlights to 1.\n");
5889                 return;
5890         }
5891         if (!r_shadow_selectedlight)
5892         {
5893                 Con_Print("No selected light.\n");
5894                 return;
5895         }
5896         R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname, r_shadow_bufferlight.coronasizescale, r_shadow_bufferlight.ambientscale, r_shadow_bufferlight.diffusescale, r_shadow_bufferlight.specularscale, r_shadow_bufferlight.flags);
5897 }
5898
5899 void R_Shadow_EditLights_Init(void)
5900 {
5901         Cvar_RegisterVariable(&r_editlights);
5902         Cvar_RegisterVariable(&r_editlights_cursordistance);
5903         Cvar_RegisterVariable(&r_editlights_cursorpushback);
5904         Cvar_RegisterVariable(&r_editlights_cursorpushoff);
5905         Cvar_RegisterVariable(&r_editlights_cursorgrid);
5906         Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
5907         Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
5908         Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
5909         Cmd_AddCommand("r_editlights_reload", R_Shadow_EditLights_Reload_f, "reloads rtlights file (or imports from .lights file or .ent file or the map itself)");
5910         Cmd_AddCommand("r_editlights_save", R_Shadow_EditLights_Save_f, "save .rtlights file for current level");
5911         Cmd_AddCommand("r_editlights_spawn", R_Shadow_EditLights_Spawn_f, "creates a light with default properties (let there be light!)");
5912         Cmd_AddCommand("r_editlights_edit", R_Shadow_EditLights_Edit_f, "changes a property on the selected light");
5913         Cmd_AddCommand("r_editlights_editall", R_Shadow_EditLights_EditAll_f, "changes a property on ALL lights at once (tip: use radiusscale and colorscale to alter these properties)");
5914         Cmd_AddCommand("r_editlights_remove", R_Shadow_EditLights_Remove_f, "remove selected light");
5915         Cmd_AddCommand("r_editlights_toggleshadow", R_Shadow_EditLights_ToggleShadow_f, "toggle on/off the shadow option on the selected light");
5916         Cmd_AddCommand("r_editlights_togglecorona", R_Shadow_EditLights_ToggleCorona_f, "toggle on/off the corona option on the selected light");
5917         Cmd_AddCommand("r_editlights_importlightentitiesfrommap", R_Shadow_EditLights_ImportLightEntitiesFromMap_f, "load lights from .ent file or map entities (ignoring .rtlights or .lights file)");
5918         Cmd_AddCommand("r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)");
5919         Cmd_AddCommand("r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
5920         Cmd_AddCommand("r_editlights_pasteinfo", R_Shadow_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)");
5921 }
5922
5923
5924
5925 /*
5926 =============================================================================
5927
5928 LIGHT SAMPLING
5929
5930 =============================================================================
5931 */
5932
5933 void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic)
5934 {
5935         VectorClear(diffusecolor);
5936         VectorClear(diffusenormal);
5937
5938         if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
5939         {
5940                 ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_refdef.scene.ambient;
5941                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
5942         }
5943         else
5944                 VectorSet(ambientcolor, 1, 1, 1);
5945
5946         if (dynamic)
5947         {
5948                 int i;
5949                 float f, v[3];
5950                 rtlight_t *light;
5951                 for (i = 0;i < r_refdef.scene.numlights;i++)
5952                 {
5953                         light = r_refdef.scene.lights[i];
5954                         Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
5955                         f = 1 - VectorLength2(v);
5956                         if (f > 0 && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
5957                                 VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
5958                 }
5959         }
5960 }