DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
r_shadow.c
Go to the documentation of this file.
1#include "quakedef.h"
2#include "r_shadow.h"
3#include "cl_collision.h"
4#include "portals.h"
5#include "image.h"
6
7static void R_Shadow_EditLights_Init(void);
8
24
25typedef enum r_shadow_shadowmode_e
26{
31
36rtlight_t **r_shadow_scenelightlist; // includes both static lights and dlights, as filtered by appropriate flags
40float r_shadow_lightshadowmap_texturescale[4]; // xy = scale, zw = offset
41float r_shadow_lightshadowmap_parameters[4]; // x = frustum width in pixels (excludes border), y = z scale, z = size of viewport, w = z center
42float r_shadow_modelshadowmap_texturescale[4]; // xy = scale, zw = offset
43float r_shadow_modelshadowmap_parameters[4]; // xyz = scale, w = shadow brightness
44#if 0
45int r_shadow_drawbuffer;
46int r_shadow_readbuffer;
47#endif
50int r_shadow_shadowmode_shadowmapping; // cached value of r_shadow_shadowmapping cvar
51int r_shadow_shadowmode_deferred; // cached value of r_shadow_deferred cvar
72
75
81
84unsigned char *shadowsides;
86
91
96
101
106
113
123
131
132// lights are reloaded when this changes
134
135// buffer for doing corona fading
136unsigned int r_shadow_occlusion_buf = 0;
137
138// used only for light filters (cubemaps)
140
141cvar_t r_shadow_bumpscale_basetexture = {CF_CLIENT, "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"};
142cvar_t r_shadow_bumpscale_bumpmap = {CF_CLIENT, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
143cvar_t r_shadow_debuglight = {CF_CLIENT, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
144cvar_t r_shadow_deferred = {CF_CLIENT | CF_ARCHIVE, "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"};
145cvar_t r_shadow_usebihculling = {CF_CLIENT, "r_shadow_usebihculling", "1", "use BIH (Bounding Interval Hierarchy) for culling lit surfaces instead of BSP (Binary Space Partitioning)"};
146cvar_t r_shadow_usenormalmap = {CF_CLIENT | CF_ARCHIVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
147cvar_t r_shadow_gloss = {CF_CLIENT | CF_ARCHIVE, "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)"};
148cvar_t r_shadow_gloss2intensity = {CF_CLIENT, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
149cvar_t r_shadow_glossintensity = {CF_CLIENT, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
150cvar_t r_shadow_glossexponent = {CF_CLIENT, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
151cvar_t r_shadow_gloss2exponent = {CF_CLIENT, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
152cvar_t r_shadow_glossexact = {CF_CLIENT, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
153cvar_t r_shadow_lightattenuationdividebias = {CF_CLIENT, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
154cvar_t r_shadow_lightattenuationlinearscale = {CF_CLIENT, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
155cvar_t r_shadow_lightintensityscale = {CF_CLIENT, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
156cvar_t r_shadow_lightradiusscale = {CF_CLIENT, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
157cvar_t r_shadow_projectdistance = {CF_CLIENT, "r_shadow_projectdistance", "0", "how far to cast shadows"};
158cvar_t r_shadow_frontsidecasting = {CF_CLIENT, "r_shadow_frontsidecasting", "1", "whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)"};
159cvar_t r_shadow_realtime_dlight = {CF_CLIENT | CF_ARCHIVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
160cvar_t r_shadow_realtime_dlight_shadows = {CF_CLIENT | CF_ARCHIVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
161cvar_t r_shadow_realtime_dlight_svbspculling = {CF_CLIENT, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
162cvar_t r_shadow_realtime_dlight_portalculling = {CF_CLIENT, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
163cvar_t r_shadow_realtime_world = {CF_CLIENT | CF_ARCHIVE, "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)"};
164cvar_t r_shadow_realtime_world_importlightentitiesfrommap = {CF_CLIENT, "r_shadow_realtime_world_importlightentitiesfrommap", "1", "load lights from .ent file or map entities at startup if no .rtlights or .lights file is present (if set to 2, always use the .ent or map entities)"};
165cvar_t r_shadow_realtime_world_lightmaps = {CF_CLIENT | CF_ARCHIVE, "r_shadow_realtime_world_lightmaps", "0", "brightness to render lightmaps when using full world lighting, try 0.5 for a tenebrae-like appearance"};
166cvar_t r_shadow_realtime_world_shadows = {CF_CLIENT | CF_ARCHIVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
167cvar_t r_shadow_realtime_world_compile = {CF_CLIENT, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
168cvar_t r_shadow_realtime_world_compileshadow = {CF_CLIENT, "r_shadow_realtime_world_compileshadow", "1", "enables compilation of shadows from world lights for higher performance rendering"};
169cvar_t r_shadow_realtime_world_compilesvbsp = {CF_CLIENT, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
170cvar_t r_shadow_realtime_world_compileportalculling = {CF_CLIENT, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
171cvar_t r_shadow_scissor = {CF_CLIENT, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
172cvar_t r_shadow_shadowmapping = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (shadow rendering by depth texture sampling)"};
173cvar_t r_shadow_shadowmapping_filterquality = {CF_CLIENT | CF_ARCHIVE, "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)"};
174cvar_t r_shadow_shadowmapping_useshadowsampler = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"};
175cvar_t r_shadow_shadowmapping_depthbits = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
176cvar_t r_shadow_shadowmapping_vsdct = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
177cvar_t r_shadow_shadowmapping_minsize = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_minsize", "32", "limit of shadowmap side size - must be at least r_shadow_shadowmapping_bordersize+2"};
178cvar_t r_shadow_shadowmapping_maxsize = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_maxsize", "512", "limit of shadowmap side size - can not be more than 1/8th of atlassize because lights store 6 sides (2x3 grid) and sometimes 12 sides (4x3 grid for shadows from EF_NOSELFSHADOW entities) and there are multiple lights..."};
179cvar_t r_shadow_shadowmapping_texturesize = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_texturesize", "8192", "size of shadowmap atlas texture - all shadowmaps are packed into this texture at frame start"};
180cvar_t r_shadow_shadowmapping_precision = {CF_CLIENT | CF_ARCHIVE, "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"};
181//cvar_t r_shadow_shadowmapping_lod_bias = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
182//cvar_t r_shadow_shadowmapping_lod_scale = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
183cvar_t r_shadow_shadowmapping_bordersize = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_bordersize", "5", "shadowmap size bias for filtering"};
184cvar_t r_shadow_shadowmapping_nearclip = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
185cvar_t r_shadow_shadowmapping_bias = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
186cvar_t r_shadow_shadowmapping_polygonfactor = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
187cvar_t r_shadow_shadowmapping_polygonoffset = {CF_CLIENT | CF_ARCHIVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
188cvar_t r_shadow_sortsurfaces = {CF_CLIENT, "r_shadow_sortsurfaces", "1", "improve performance by sorting illuminated surfaces by texture"};
189cvar_t r_shadow_culllights_pvs = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_pvs", "1", "check if light overlaps any visible bsp leafs when determining if the light is visible"};
190cvar_t r_shadow_culllights_trace = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace", "1", "use raytraces from the eye to random places within light bounds to determine if the light is visible"};
191cvar_t r_shadow_culllights_trace_eyejitter = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_eyejitter", "16", "offset eye location randomly by this much"};
192cvar_t r_shadow_culllights_trace_enlarge = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_enlarge", "0", "make light bounds bigger by *(1.0+enlarge)"};
193cvar_t r_shadow_culllights_trace_expand = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_expand", "8", "make light bounds bigger by this many units"};
194cvar_t r_shadow_culllights_trace_pad = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_pad", "8", "accept traces that hit within this many units of the light bounds"};
195cvar_t r_shadow_culllights_trace_samples = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_samples", "16", "use this many traces to random positions (in addition to center trace)"};
196cvar_t r_shadow_culllights_trace_tempsamples = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_tempsamples", "16", "use this many traces if the light was created by csqc (no inter-frame caching), -1 disables the check (to avoid flicker entirely)"};
197cvar_t r_shadow_culllights_trace_delay = {CF_CLIENT | CF_ARCHIVE, "r_shadow_culllights_trace_delay", "1", "light will be considered visible for this many seconds after any trace connects"};
198cvar_t r_shadow_bouncegrid = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid", "0", "perform particle tracing for indirect lighting (Global Illumination / radiosity) using a 3D texture covering the scene, only active on levels with realtime lights active (r_shadow_realtime_world is usually required for these)"};
199cvar_t r_shadow_bouncegrid_blur = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_blur", "0", "apply a 1-radius blur on bouncegrid to denoise it and deal with boundary issues with surfaces"};
200cvar_t r_shadow_bouncegrid_dynamic_bounceminimumintensity = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_bounceminimumintensity", "0.05", "stop bouncing once intensity drops below this fraction of the original particle color"};
201cvar_t r_shadow_bouncegrid_dynamic_culllightpaths = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_culllightpaths", "0", "skip accumulating light in the bouncegrid texture where the light paths are out of view (dynamic mode only)"};
202cvar_t r_shadow_bouncegrid_dynamic_directionalshading = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_directionalshading", "1", "use diffuse shading rather than ambient, 3D texture becomes 8x as many pixels to hold the additional data"};
203cvar_t r_shadow_bouncegrid_dynamic_dlightparticlemultiplier = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_dlightparticlemultiplier", "1", "if set to a high value like 16 this can make dlights look great, but 0 is recommended for performance reasons"};
204cvar_t r_shadow_bouncegrid_dynamic_hitmodels = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_hitmodels", "0", "enables hitting character model geometry (SLOW)"};
205cvar_t r_shadow_bouncegrid_dynamic_lightradiusscale = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_lightradiusscale", "5", "particles stop at this fraction of light radius (can be more than 1)"};
206cvar_t r_shadow_bouncegrid_dynamic_maxbounce = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_maxbounce", "5", "maximum number of bounces for a particle (minimum is 0)"};
207cvar_t r_shadow_bouncegrid_dynamic_maxphotons = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_maxphotons", "25000", "upper bound on photons to shoot per update, divided proportionately between lights - normally the number of photons is calculated by energyperphoton"};
208cvar_t r_shadow_bouncegrid_dynamic_quality = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_quality", "1", "amount of photons that should be fired (this is multiplied by spacing ^ 2 to make it adaptive with spacing changes)"};
209cvar_t r_shadow_bouncegrid_dynamic_spacing = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_spacing", "64", "unit size of bouncegrid pixel"};
210cvar_t r_shadow_bouncegrid_dynamic_updateinterval = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_updateinterval", "0", "update bouncegrid texture once per this many seconds, useful values are 0, 0.05, or 1000000"};
211cvar_t r_shadow_bouncegrid_dynamic_x = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_x", "64", "maximum texture size of bouncegrid on X axis"};
212cvar_t r_shadow_bouncegrid_dynamic_y = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_y", "64", "maximum texture size of bouncegrid on Y axis"};
213cvar_t r_shadow_bouncegrid_dynamic_z = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_dynamic_z", "32", "maximum texture size of bouncegrid on Z axis"};
214cvar_t r_shadow_bouncegrid_floatcolors = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_floatcolors", "1", "upload texture as RGBA16F (or RGBA32F when set to 2) rather than RGBA8 format - this gives more dynamic range and accuracy"};
215cvar_t r_shadow_bouncegrid_includedirectlighting = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_includedirectlighting", "0", "allows direct lighting to be recorded, not just indirect (gives an effect somewhat like r_shadow_realtime_world_lightmaps)"};
216cvar_t r_shadow_bouncegrid_intensity = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_intensity", "4", "overall brightness of bouncegrid texture"};
217cvar_t r_shadow_bouncegrid_lightpathsize = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_lightpathsize", "64", "radius (in game units) of the light path for accumulation of light in the bouncegrid texture"};
218cvar_t r_shadow_bouncegrid_normalizevectors = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_normalizevectors", "1", "normalize random vectors (otherwise their length can vary, which dims the lighting further from the light)"};
219cvar_t r_shadow_bouncegrid_particlebounceintensity = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_particlebounceintensity", "4", "amount of energy carried over after each bounce, this is a multiplier of texture color and the result is clamped to 1 or less, to prevent adding energy on each bounce"};
220cvar_t r_shadow_bouncegrid_particleintensity = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_particleintensity", "1", "brightness of particles contributing to bouncegrid texture"};
221cvar_t r_shadow_bouncegrid_rng_seed = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_rng_seed", "0", "0+ = use this number as RNG seed, -1 = use time instead for disco-like craziness in dynamic mode"};
222cvar_t r_shadow_bouncegrid_rng_type = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_rng_type", "0", "0 = Lehmer 128bit RNG (slow but high quality), 1 = lhcheeserand 32bit RNG (quick)"};
223cvar_t r_shadow_bouncegrid_static = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static", "1", "use static radiosity solution (high quality) rather than dynamic (splotchy)"};
224cvar_t r_shadow_bouncegrid_static_bounceminimumintensity = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_bounceminimumintensity", "0.01", "stop bouncing once intensity drops below this fraction of the original particle color"};
225cvar_t r_shadow_bouncegrid_static_directionalshading = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_directionalshading", "1", "whether to use directionalshading when in static mode"};
226cvar_t r_shadow_bouncegrid_static_lightradiusscale = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_lightradiusscale", "5", "particles stop at this fraction of light radius (can be more than 1) when in static mode"};
227cvar_t r_shadow_bouncegrid_static_maxbounce = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_maxbounce", "5", "maximum number of bounces for a particle (minimum is 0) in static mode"};
228cvar_t r_shadow_bouncegrid_static_maxphotons = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_maxphotons", "250000", "upper bound on photons in static mode"};
229cvar_t r_shadow_bouncegrid_static_quality = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_quality", "16", "amount of photons that should be fired (this is multiplied by spacing ^ 2 to make it adaptive with spacing changes)"};
230cvar_t r_shadow_bouncegrid_static_spacing = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_static_spacing", "64", "unit size of bouncegrid pixel when in static mode"};
231cvar_t r_shadow_bouncegrid_subsamples = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_subsamples", "1", "when generating the texture, sample this many points along each dimension (multisampling uses more compute but not more memory bandwidth)"};
232cvar_t r_shadow_bouncegrid_threaded = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_threaded", "1", "enables use of taskqueue_maxthreads to perform the traces and slice rendering of bouncegrid"};
233cvar_t r_coronas = {CF_CLIENT | CF_ARCHIVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
234cvar_t r_coronas_occlusionsizescale = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
235cvar_t r_coronas_occlusionquery = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility, requires OpenGL 4.4"};
236cvar_t gl_flashblend = {CF_CLIENT | CF_ARCHIVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
237cvar_t r_editlights = {CF_CLIENT, "r_editlights", "0", "enables .rtlights file editing mode"};
238cvar_t r_editlights_cursordistance = {CF_CLIENT, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
239cvar_t r_editlights_cursorpushback = {CF_CLIENT, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
240cvar_t r_editlights_cursorpushoff = {CF_CLIENT, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
241cvar_t r_editlights_cursorgrid = {CF_CLIENT, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
242cvar_t r_editlights_quakelightsizescale = {CF_CLIENT | CF_ARCHIVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
243cvar_t r_editlights_drawproperties = {CF_CLIENT, "r_editlights_drawproperties", "1", "draw properties of currently selected light"};
244cvar_t r_editlights_current_origin = {CF_CLIENT, "r_editlights_current_origin", "0 0 0", "origin of selected light"};
245cvar_t r_editlights_current_angles = {CF_CLIENT, "r_editlights_current_angles", "0 0 0", "angles of selected light"};
246cvar_t r_editlights_current_color = {CF_CLIENT, "r_editlights_current_color", "1 1 1", "color of selected light"};
247cvar_t r_editlights_current_radius = {CF_CLIENT, "r_editlights_current_radius", "0", "radius of selected light"};
248cvar_t r_editlights_current_corona = {CF_CLIENT, "r_editlights_current_corona", "0", "corona intensity of selected light"};
249cvar_t r_editlights_current_coronasize = {CF_CLIENT, "r_editlights_current_coronasize", "0", "corona size of selected light"};
250cvar_t r_editlights_current_style = {CF_CLIENT, "r_editlights_current_style", "0", "style of selected light"};
251cvar_t r_editlights_current_shadows = {CF_CLIENT, "r_editlights_current_shadows", "0", "shadows flag of selected light"};
252cvar_t r_editlights_current_cubemap = {CF_CLIENT, "r_editlights_current_cubemap", "0", "cubemap of selected light"};
253cvar_t r_editlights_current_ambient = {CF_CLIENT, "r_editlights_current_ambient", "0", "ambient intensity of selected light"};
254cvar_t r_editlights_current_diffuse = {CF_CLIENT, "r_editlights_current_diffuse", "1", "diffuse intensity of selected light"};
255cvar_t r_editlights_current_specular = {CF_CLIENT, "r_editlights_current_specular", "1", "specular intensity of selected light"};
256cvar_t r_editlights_current_normalmode = {CF_CLIENT, "r_editlights_current_normalmode", "0", "normalmode flag of selected light"};
257cvar_t r_editlights_current_realtimemode = {CF_CLIENT, "r_editlights_current_realtimemode", "0", "realtimemode flag of selected light"};
258
260
261// note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
262#define ATTENTABLESIZE 256
263// 1D gradient, 2D circle and 3D sphere attenuation textures
264#define ATTEN1DSIZE 32
265#define ATTEN2DSIZE 64
266#define ATTEN3DSIZE 32
267
268static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
269static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
271
278
279extern int con_vislines;
280
283void R_Shadow_SaveWorldLights(void);
284void R_Shadow_LoadWorldLights(void);
285void R_Shadow_LoadLightsFile(void);
288static void R_Shadow_MakeTextures(void);
289
290#define EDLIGHTSPRSIZE 8
297
298static void R_Shadow_DrawModelShadowMaps(void);
299static void R_Shadow_MakeShadowMap(int texturesize);
300static void R_Shadow_MakeVSDCT(void);
301static void R_Shadow_SetShadowMode(void)
302{
317 {
318 switch (vid.renderpath)
319 {
320 case RENDERPATH_GL32:
322 {
325 else if ((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && r_shadow_shadowmapshadowsampler)
326 {
329 }
332 else if ((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
334 else
336 }
337 else
338 {
341 {
342 case 1:
343 break;
344 case 2:
346 break;
347 case 3:
349 break;
350 case 4:
352 break;
353 }
354 }
358 break;
359 case RENDERPATH_GLES2:
361 break;
362 }
363 }
364
365 switch (r_shadow_shadowmode)
366 {
369 break;
371 break;
372 }
373
376}
377
379{
380 switch (r_shadow_shadowmode)
381 {
383 return true;
385 return false;
386 }
387 return false;
388}
389
415
416static void r_shadow_start(void)
417{
418 // allocate vertex processing arrays
432 r_shadow_fbo2d = 0;
433
435
446 maxvertexupdate = 0;
449 vertexupdatenum = 0;
450 maxshadowmark = 0;
451 numshadowmark = 0;
454 shadowmarkcount = 0;
455 maxshadowsides = 0;
456 numshadowsides = 0;
471
474
475 // determine renderpath specific capabilities, we don't need to figure
476 // these out per frame...
477 switch(vid.renderpath)
478 {
479 case RENDERPATH_GL32:
482 break;
483 case RENDERPATH_GLES2:
484 // for performance reasons, do not use directional shading on GLES devices
486 break;
487 }
488}
489
501
502static void R_Shadow_FreeDeferred(void);
503static void r_shadow_shutdown(void)
504{
506
508
513
526 if (shadowelements)
529 if (shadowvertex3f)
532 maxvertexupdate = 0;
533 if (vertexupdate)
536 if (vertexremap)
539 vertexupdatenum = 0;
540 maxshadowmark = 0;
541 numshadowmark = 0;
542 if (shadowmark)
545 if (shadowmarklist)
548 shadowmarkcount = 0;
549 maxshadowsides = 0;
550 numshadowsides = 0;
551 if (shadowsides)
554 if (shadowsideslist)
583}
584
600
602{
643// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
644// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
708 maxvertexupdate = 0;
711 vertexupdatenum = 0;
712 maxshadowmark = 0;
713 numshadowmark = 0;
716 shadowmarkcount = 0;
717 maxshadowsides = 0;
718 numshadowsides = 0;
732}
733
735{
736 {
737 {0.5, 0.0, 0.0, 0.5},
738 {0.0, 0.5, 0.0, 0.5},
739 {0.0, 0.0, 0.5, 0.5},
740 {0.0, 0.0, 0.0, 1.0}
741 }
742};
743
745{
746 {
747 {0.0, 0.0, 0.5, 0.5},
748 {0.0, 0.0, 0.0, 0.5},
749 {0.0, 0.0, 0.0, 0.5},
750 {0.0, 0.0, 0.0, 1.0}
751 }
752};
753
754static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
755{
756 numvertices = ((numvertices + 255) & ~255) * vertscale;
757 numtriangles = ((numtriangles + 255) & ~255) * triscale;
758 // make sure shadowelements is big enough for this volume
759 if (maxshadowtriangles < numtriangles)
760 {
761 maxshadowtriangles = numtriangles;
762 if (shadowelements)
764 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
765 }
766 // make sure shadowvertex3f is big enough for this volume
767 if (maxshadowvertices < numvertices)
768 {
769 maxshadowvertices = numvertices;
770 if (shadowvertex3f)
772 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
773 }
774}
775
776static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
777{
778 int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
779 int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
780 int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
781 int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
782 if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
783 {
790 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
794 }
795 if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
796 {
803 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
807 }
808 if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
809 {
812 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
814 }
815 if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
816 {
819 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
821 }
822}
823
825{
826 // make sure shadowmark is big enough for this volume
827 if (maxshadowmark < numtris)
828 {
829 maxshadowmark = numtris;
830 if (shadowmark)
832 if (shadowmarklist)
836 shadowmarkcount = 0;
837 }
839 // if shadowmarkcount wrapped we clear the array and adjust accordingly
840 if (shadowmarkcount == 0)
841 {
842 shadowmarkcount = 1;
843 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
844 }
845 numshadowmark = 0;
846}
847
849{
850 if (maxshadowsides < numtris)
851 {
852 maxshadowsides = numtris;
853 if (shadowsides)
855 if (shadowsideslist)
857 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
859 }
860 numshadowsides = 0;
861}
862
863int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
864{
865 // p1, p2, p3 are in the cubemap's local coordinate system
866 // bias = border/(size - border)
867 int mask = 0x3F;
868
869 float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
870 dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
871 dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
872 if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
873 mask &= (3<<4)
874 | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
875 | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
876 | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
877 if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
878 mask &= (3<<4)
879 | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
880 | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
881 | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
882
883 dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
884 dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
885 dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
886 if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
887 mask &= (3<<0)
888 | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
889 | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
890 | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
891 if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
892 mask &= (3<<0)
893 | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
894 | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
895 | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
896
897 dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
898 dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
899 dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
900 if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
901 mask &= (3<<2)
902 | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
903 | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
904 | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
905 if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
906 mask &= (3<<2)
907 | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
908 | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
909 | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
910
911 return mask;
912}
913
914static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
915{
916 vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
917 float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
918 int mask = 0x3F;
919
920 VectorSubtract(maxs, mins, radius);
921 VectorScale(radius, 0.5f, radius);
922 VectorAdd(mins, radius, center);
923 Matrix4x4_Transform(worldtolight, center, lightcenter);
924 Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
925 VectorSubtract(lightcenter, lightradius, pmin);
926 VectorAdd(lightcenter, lightradius, pmax);
927
928 dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
929 dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
930 if(ap1 > bias*an1 && ap2 > bias*an2)
931 mask &= (3<<4)
932 | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
933 | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
934 if(an1 > bias*ap1 && an2 > bias*ap2)
935 mask &= (3<<4)
936 | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
937 | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
938
939 dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
940 dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
941 if(ap1 > bias*an1 && ap2 > bias*an2)
942 mask &= (3<<0)
943 | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
944 | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
945 if(an1 > bias*ap1 && an2 > bias*ap2)
946 mask &= (3<<0)
947 | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
948 | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
949
950 dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
951 dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
952 if(ap1 > bias*an1 && ap2 > bias*an2)
953 mask &= (3<<2)
954 | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
955 | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
956 if(an1 > bias*ap1 && an2 > bias*ap2)
957 mask &= (3<<2)
958 | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
959 | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
960
961 return mask;
962}
963
964#define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
965
966int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
967{
968 // p is in the cubemap's local coordinate system
969 // bias = border/(size - border)
970 float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
971 float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
972 float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
973 int mask = 0x3F;
974 if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
975 if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
976 if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
977 if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
978 if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
979 if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
980 return mask;
981}
982
983static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
984{
985 int i;
986 vec3_t o, p, n;
987 int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
988 float scale = (size - 2*border)/size, len;
989 float bias = border / (float)(size - border), dp, dn, ap, an;
990 // check if cone enclosing side would cross frustum plane
991 scale = 2 / (scale*scale + 2);
993 for (i = 0;i < 5;i++)
994 {
995 if (PlaneDiff(o, &r_refdef.view.frustum[i]) > -0.03125)
996 continue;
998 len = scale*VectorLength2(n);
999 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1000 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1001 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1002 }
1003 if (PlaneDiff(o, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1004 {
1006 len = scale*VectorLength2(n);
1007 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1008 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1009 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1010 }
1011 // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1012 // check if frustum corners/origin cross plane sides
1013#if 1
1014 // infinite version, assumes frustum corners merely give direction and extend to infinite distance
1016 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1017 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1018 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1019 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1020 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1021 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1022 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1023 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1024 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1025 for (i = 0;i < 4;i++)
1026 {
1028 VectorSubtract(n, p, n);
1029 dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
1030 if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
1031 if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
1032 dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
1033 if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
1034 if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
1035 dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
1036 if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
1037 if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
1038 }
1039#else
1040 // finite version, assumes corners are a finite distance from origin dependent on far plane
1041 for (i = 0;i < 5;i++)
1042 {
1044 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1045 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1046 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1047 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1048 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1049 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1050 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1051 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1052 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1053 }
1054#endif
1055 return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1056}
1057
1058int 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)
1059{
1060 int t, tend;
1061 const int *e;
1062 const float *v[3];
1063 float normal[3];
1064 vec3_t p[3];
1065 float bias;
1066 int mask, surfacemask = 0;
1067 if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1068 return 0;
1070 tend = firsttriangle + numtris;
1071 if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1072 {
1073 // surface box entirely inside light box, no box cull
1074 if (projectdirection)
1075 {
1076 for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1077 {
1078 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1079 TriangleNormal(v[0], v[1], v[2], normal);
1080 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1081 {
1082 Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1083 mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1084 surfacemask |= mask;
1085 if(totals)
1086 {
1087 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;
1090 }
1091 }
1092 }
1093 }
1094 else
1095 {
1096 for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1097 {
1098 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1099 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1100 {
1101 Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1102 mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1103 surfacemask |= mask;
1104 if(totals)
1105 {
1106 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;
1109 }
1110 }
1111 }
1112 }
1113 }
1114 else
1115 {
1116 // surface box not entirely inside light box, cull each triangle
1117 if (projectdirection)
1118 {
1119 for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1120 {
1121 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1122 TriangleNormal(v[0], v[1], v[2], normal);
1123 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1124 && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1125 {
1126 Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1127 mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1128 surfacemask |= mask;
1129 if(totals)
1130 {
1131 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;
1134 }
1135 }
1136 }
1137 }
1138 else
1139 {
1140 for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1141 {
1142 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1143 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1144 && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1145 {
1146 Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1147 mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1148 surfacemask |= mask;
1149 if(totals)
1150 {
1151 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;
1154 }
1155 }
1156 }
1157 }
1158 }
1159 return surfacemask;
1160}
1161
1162void 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)
1163{
1164 int i, j, outtriangles = 0;
1165 int *outelement3i[6];
1166 if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1167 return;
1168 outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1169 // make sure shadowelements is big enough for this mesh
1170 if (maxshadowtriangles < outtriangles)
1171 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1172
1173 // compute the offset and size of the separate index lists for each cubemap side
1174 outtriangles = 0;
1175 for (i = 0;i < 6;i++)
1176 {
1177 outelement3i[i] = shadowelements + outtriangles * 3;
1180 outtriangles += sidetotals[i];
1181 }
1182
1183 // gather up the (sparse) triangles into separate index lists for each cubemap side
1184 for (i = 0;i < numsidetris;i++)
1185 {
1186 const int *element = elements + sidetris[i] * 3;
1187 for (j = 0;j < 6;j++)
1188 {
1189 if (sides[i] & (1 << j))
1190 {
1191 outelement3i[j][0] = element[0];
1192 outelement3i[j][1] = element[1];
1193 outelement3i[j][2] = element[2];
1194 outelement3i[j] += 3;
1195 }
1196 }
1197 }
1198
1200}
1201
1203{
1204 float dx, dy;
1205 int x, y, a;
1206 unsigned char pixels[32][32][4];
1207 for (y = 0;y < 32;y++)
1208 {
1209 dy = (y - 15.5f) * (1.0f / 16.0f);
1210 for (x = 0;x < 32;x++)
1211 {
1212 dx = (x - 15.5f) * (1.0f / 16.0f);
1213 a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1214 a = bound(0, a, 255);
1215 pixels[y][x][0] = a;
1216 pixels[y][x][1] = a;
1217 pixels[y][x][2] = a;
1218 pixels[y][x][3] = 255;
1219 }
1220 }
1221 r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32, 0, 0, 0, false);
1222}
1223
1224static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1225{
1226 float dist = sqrt(x*x+y*y+z*z);
1227 float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1228 // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1229 return bound(0, (unsigned int)(intensity * 256.0f), 255) * 0x01010101U;
1230}
1231
1232static void R_Shadow_MakeTextures(void)
1233{
1234 int x;
1235 float intensity, dist;
1236 unsigned int *data;
1243 // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1244 for (x = 0;x <= ATTENTABLESIZE;x++)
1245 {
1246 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1247 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1249 }
1250 // 1D gradient texture
1251 for (x = 0;x < ATTEN1DSIZE;x++)
1252 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1254 Mem_Free(data);
1255
1257
1258 // Editor light sprites
1259 r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1260 "................"
1261 ".3............3."
1262 "..5...2332...5.."
1263 "...7.3....3.7..."
1264 "....7......7...."
1265 "...3.7....7.3..."
1266 "..2...7..7...2.."
1267 "..3..........3.."
1268 "..3..........3.."
1269 "..2...7..7...2.."
1270 "...3.7....7.3..."
1271 "....7......7...."
1272 "...7.3....3.7..."
1273 "..5...2332...5.."
1274 ".3............3."
1275 "................"
1277 r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1278 "................"
1279 "................"
1280 "......1111......"
1281 "....11233211...."
1282 "...1234554321..."
1283 "...1356776531..."
1284 "..124677776421.."
1285 "..135777777531.."
1286 "..135777777531.."
1287 "..124677776421.."
1288 "...1356776531..."
1289 "...1234554321..."
1290 "....11233211...."
1291 "......1111......"
1292 "................"
1293 "................"
1295 r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1296 "................"
1297 "................"
1298 "......1111......"
1299 "....11233211...."
1300 "...1234554321..."
1301 "...1356226531..."
1302 "..12462..26421.."
1303 "..1352....2531.."
1304 "..1352....2531.."
1305 "..12462..26421.."
1306 "...1356226531..."
1307 "...1234554321..."
1308 "....11233211...."
1309 "......1111......"
1310 "................"
1311 "................"
1313 r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1314 "................"
1315 "................"
1316 "......2772......"
1317 "....27755772...."
1318 "..277533335772.."
1319 "..753333333357.."
1320 "..777533335777.."
1321 "..735775577537.."
1322 "..733357753337.."
1323 "..733337733337.."
1324 "..753337733357.."
1325 "..277537735772.."
1326 "....27777772...."
1327 "......2772......"
1328 "................"
1329 "................"
1331 r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1332 "................"
1333 "................"
1334 "......2772......"
1335 "....27722772...."
1336 "..2772....2772.."
1337 "..72........27.."
1338 "..7772....2777.."
1339 "..7.27722772.7.."
1340 "..7...2772...7.."
1341 "..7....77....7.."
1342 "..72...77...27.."
1343 "..2772.77.2772.."
1344 "....27777772...."
1345 "......2772......"
1346 "................"
1347 "................"
1349 r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1350 "................"
1351 ".777752..257777."
1352 ".742........247."
1353 ".72..........27."
1354 ".7............7."
1355 ".5............5."
1356 ".2............2."
1357 "................"
1358 "................"
1359 ".2............2."
1360 ".5............5."
1361 ".7............7."
1362 ".72..........27."
1363 ".742........247."
1364 ".777752..257777."
1365 "................"
1367}
1368
1370{
1371#if 0
1372 GLint drawbuffer;
1373 GLint readbuffer;
1374#endif
1375
1379
1383 GL_DepthRange(0, 1);
1385 GL_DepthTest(true);
1386 GL_DepthMask(false);
1387 GL_Color(0, 0, 0, 1);
1389
1392
1394#if 0
1395 qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1396 qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1397 r_shadow_drawbuffer = drawbuffer;
1398 r_shadow_readbuffer = readbuffer;
1399#endif
1402}
1403
1405{
1406 rsurface.rtlight = rtlight;
1407}
1408
1429
1435
1436static void R_Shadow_MakeVSDCT(void)
1437{
1438 // maps to a 2x3 texture rectangle with normalized coordinates
1439 // +-
1440 // XX
1441 // YY
1442 // ZZ
1443 // stores abs(dir.xy), offset.xy/2.5
1444 unsigned char data[4*6] =
1445 {
1446 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
1447 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
1448 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
1449 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
1450 0, 0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
1451 0, 0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
1452 };
1454}
1455
1479
1481{
1482 r_viewport_t viewport;
1483 float clearcolor[4];
1484
1485 // if they don't exist, create our textures now
1490
1491 // we're setting up to render shadowmaps, so change rendermode
1493
1498 else
1500 R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
1502 GL_DepthMask(true);
1503 GL_DepthTest(true);
1504
1505 // we have to set a viewport to clear anything in some renderpaths (D3D)
1507 R_SetViewport(&viewport);
1508 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
1510 GL_ColorMask(1, 1, 1, 1);
1511 else
1512 GL_ColorMask(0, 0, 0, 0);
1513 switch (vid.renderpath)
1514 {
1515 case RENDERPATH_GL32:
1516 case RENDERPATH_GLES2:
1518 break;
1519 }
1520 Vector4Set(clearcolor, 1, 1, 1, 1);
1522 GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
1523 else
1524 GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
1525}
1526
1528{
1531 float farclip = 1.0f;
1532 float bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
1538 r_shadow_lightshadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
1540 r_shadow_lightshadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
1542 {
1543 // completely different meaning than in depthtexture approach
1546 }
1547}
1548
1549static void R_Shadow_RenderMode_ShadowMap(int side, int size, int x, int y)
1550{
1551 float nearclip, farclip;
1552 r_viewport_t viewport;
1553 int flipped;
1554
1556 {
1558
1563 else
1565 R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
1567 GL_DepthMask(true);
1568 GL_DepthTest(true);
1569 }
1570
1572 farclip = 1.0f;
1573
1575 R_SetViewport(&viewport);
1576 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
1577 flipped = (side & 1) ^ (side >> 2);
1580
1582 GL_ColorMask(1,1,1,1);
1583 else
1584 GL_ColorMask(0,0,0,0);
1585 switch(vid.renderpath)
1586 {
1587 case RENDERPATH_GL32:
1588 case RENDERPATH_GLES2:
1590 break;
1591 }
1592
1593 // used in R_Q1BSP_DrawShadowMap code to check surfacesides[]
1595}
1596
1597void R_Shadow_RenderMode_Lighting(qbool transparent, qbool shadowmapping, qbool noselfshadowpass)
1598{
1600 if (transparent)
1601 {
1606 }
1607 if (shadowmapping)
1611 if (!transparent)
1613 // do global setup needed for the chosen lighting mode
1616 r_shadow_usingshadowmap2d = shadowmapping;
1618}
1619
1620static const unsigned short bboxelements[36] =
1621{
1622 5, 1, 3, 5, 3, 7,
1623 6, 2, 0, 6, 0, 4,
1624 7, 3, 2, 7, 2, 6,
1625 4, 0, 1, 4, 1, 5,
1626 4, 5, 7, 4, 7, 6,
1627 1, 0, 2, 1, 2, 3,
1628};
1629
1630static const float bboxpoints[8][3] =
1631{
1632 {-1,-1,-1},
1633 { 1,-1,-1},
1634 {-1, 1,-1},
1635 { 1, 1,-1},
1636 {-1,-1, 1},
1637 { 1,-1, 1},
1638 {-1, 1, 1},
1639 { 1, 1, 1},
1640};
1641
1643{
1644 int i;
1645 float vertex3f[8*3];
1647// do global setup needed for the chosen lighting mode
1654 else
1656
1657 r_shadow_usingshadowmap2d = shadowmapping;
1658
1659 // render the lighting
1661 for (i = 0;i < 8;i++)
1662 Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
1663 GL_ColorMask(1,1,1,1);
1664 GL_DepthMask(false);
1665 GL_DepthRange(0, 1);
1666 GL_PolygonOffset(0, 0);
1667 GL_DepthTest(true);
1670 R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0);
1671 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
1672}
1673
1675{
1677 int lightindex;
1678 int range;
1679 dlight_t *light;
1680 rtlight_t *rtlight;
1681 vec3_t lightcolor;
1682
1683 // see if there are really any lights to render...
1684 if (enable && r_shadow_bouncegrid_static.integer)
1685 {
1686 enable = false;
1687 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1688 for (lightindex = 0;lightindex < range;lightindex++)
1689 {
1691 if (!light || !(light->flags & flag))
1692 continue;
1693 rtlight = &light->rtlight;
1694 // when static, we skip styled lights because they tend to change...
1695 if (rtlight->style > 0)
1696 continue;
1697 VectorScale(rtlight->color, (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale), lightcolor);
1698 if (!VectorLength2(lightcolor))
1699 continue;
1700 enable = true;
1701 break;
1702 }
1703 }
1704
1705 return enable;
1706}
1707
1709{
1714
1715 // prevent any garbage in alignment padded areas as we'll be using memcmp
1716 memset(settings, 0, sizeof(*settings));
1717
1718 // build up a complete collection of the desired settings, so that memcmp can be used to compare parameters
1719 settings->staticmode = s;
1720 settings->blur = r_shadow_bouncegrid_blur.integer != 0;
1722 settings->lightpathsize = bound(0.0f, r_shadow_bouncegrid_lightpathsize.value, 1024.0f);
1730 settings->particleintensity = r_shadow_bouncegrid_particleintensity.value * (settings->directionalshading ? 4.0f : 1.0f) / 65536.0f;
1732 settings->energyperphoton = 4096.0f / quality;
1733 settings->spacing[0] = spacing;
1734 settings->spacing[1] = spacing;
1735 settings->spacing[2] = spacing;
1738 settings->bounceminimumintensity2 = bounceminimumintensity * bounceminimumintensity;
1741
1742 // bound the values for sanity
1743 settings->maxphotons = bound(1, settings->maxphotons, 25000000);
1744 settings->lightradiusscale = bound(0.0001f, settings->lightradiusscale, 1024.0f);
1745 settings->maxbounce = bound(0, settings->maxbounce, 16);
1746 settings->spacing[0] = bound(1, settings->spacing[0], 512);
1747 settings->spacing[1] = bound(1, settings->spacing[1], 512);
1748 settings->spacing[2] = bound(1, settings->spacing[2], 512);
1749}
1750
1752{
1753 float m[16];
1754 int c[4];
1755 int resolution[3];
1756 int numpixels;
1757 vec3_t ispacing;
1758 vec3_t maxs = {0,0,0};
1759 vec3_t mins = {0,0,0};
1760 vec3_t size;
1761 vec3_t spacing;
1763
1764 // get the spacing values
1765 spacing[0] = settings->spacing[0];
1766 spacing[1] = settings->spacing[1];
1767 spacing[2] = settings->spacing[2];
1768 ispacing[0] = 1.0f / spacing[0];
1769 ispacing[1] = 1.0f / spacing[1];
1770 ispacing[2] = 1.0f / spacing[2];
1771
1772 // calculate texture size enclosing entire world bounds at the spacing
1774 {
1775 int lightindex;
1776 int range;
1777 qbool bounds_set = false;
1778 dlight_t *light;
1779 rtlight_t *rtlight;
1780
1781 // calculate bounds enclosing world lights as they should be noticably tighter
1782 // than the world bounds on maps with unlit monster containers (see e1m7 etc)
1783 range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1784 for (lightindex = 0;lightindex < range;lightindex++)
1785 {
1786 const vec_t *rtlmins, *rtlmaxs;
1787
1789 if (!light)
1790 continue;
1791
1792 rtlight = &light->rtlight;
1793 rtlmins = rtlight->cullmins;
1794 rtlmaxs = rtlight->cullmaxs;
1795
1796 if (!bounds_set)
1797 {
1798 VectorCopy(rtlmins, mins);
1799 VectorCopy(rtlmaxs, maxs);
1800 bounds_set = true;
1801 }
1802 else
1803 {
1804 mins[0] = min(mins[0], rtlmins[0]);
1805 mins[1] = min(mins[1], rtlmins[1]);
1806 mins[2] = min(mins[2], rtlmins[2]);
1807 maxs[0] = max(maxs[0], rtlmaxs[0]);
1808 maxs[1] = max(maxs[1], rtlmaxs[1]);
1809 maxs[2] = max(maxs[2], rtlmaxs[2]);
1810 }
1811 }
1812
1813 // limit to no larger than the world bounds
1820
1821 VectorMA(mins, -2.0f, spacing, mins);
1822 VectorMA(maxs, 2.0f, spacing, maxs);
1823 }
1824 else
1825 {
1826 VectorSet(mins, -1048576.0f, -1048576.0f, -1048576.0f);
1827 VectorSet(maxs, 1048576.0f, 1048576.0f, 1048576.0f);
1828 }
1830 // now we can calculate the resolution we want
1831 c[0] = (int)floor(size[0] / spacing[0] + 0.5f);
1832 c[1] = (int)floor(size[1] / spacing[1] + 0.5f);
1833 c[2] = (int)floor(size[2] / spacing[2] + 0.5f);
1834 // figure out the exact texture size (honoring power of 2 if required)
1835 resolution[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
1836 resolution[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
1837 resolution[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
1838 size[0] = spacing[0] * resolution[0];
1839 size[1] = spacing[1] * resolution[1];
1840 size[2] = spacing[2] * resolution[2];
1841
1842 // if dynamic we may or may not want to use the world bounds
1843 // if the dynamic size is smaller than the world bounds, use it instead
1844 if (!settings->staticmode && (r_shadow_bouncegrid_dynamic_x.integer * r_shadow_bouncegrid_dynamic_y.integer * r_shadow_bouncegrid_dynamic_z.integer < resolution[0] * resolution[1] * resolution[2]))
1845 {
1846 // we know the resolution we want
1850 // now we can calculate the texture size
1851 resolution[0] = bound(4, c[0], (int)vid.maxtexturesize_3d);
1852 resolution[1] = bound(4, c[1], (int)vid.maxtexturesize_3d);
1853 resolution[2] = bound(4, c[2], (int)vid.maxtexturesize_3d);
1854 size[0] = spacing[0] * resolution[0];
1855 size[1] = spacing[1] * resolution[1];
1856 size[2] = spacing[2] * resolution[2];
1857 // center the rendering on the view
1858 mins[0] = floor(r_refdef.view.origin[0] * ispacing[0] + 0.5f) * spacing[0] - 0.5f * size[0];
1859 mins[1] = floor(r_refdef.view.origin[1] * ispacing[1] + 0.5f) * spacing[1] - 0.5f * size[1];
1860 mins[2] = floor(r_refdef.view.origin[2] * ispacing[2] + 0.5f) * spacing[2] - 0.5f * size[2];
1861 }
1862
1863 // recalculate the maxs in case the resolution was not satisfactory
1865
1866 // check if this changed the texture size
1875
1876 // reallocate pixels for this update if needed...
1878 r_shadow_bouncegrid_state.pixelsperband = resolution[0]*resolution[1]*resolution[2];
1881 if (r_shadow_bouncegrid_state.numpixels != numpixels)
1882 {
1884
1886
1888 }
1889
1890 // update the bouncegrid matrix to put it in the world properly
1891 memset(m, 0, sizeof(m));
1892 m[0] = 1.0f / r_shadow_bouncegrid_state.size[0];
1893 m[3] = -r_shadow_bouncegrid_state.mins[0] * m[0];
1894 m[5] = 1.0f / r_shadow_bouncegrid_state.size[1];
1895 m[7] = -r_shadow_bouncegrid_state.mins[1] * m[5];
1896 m[10] = 1.0f / r_shadow_bouncegrid_state.size[2];
1897 m[11] = -r_shadow_bouncegrid_state.mins[2] * m[10];
1898 m[15] = 1.0f;
1900}
1901
1903{
1904 // check material at shadoworigin to see what the initial refractive index should be
1905 int hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK;
1906 int skipsupercontentsmask = 0;
1907 int skipmaterialflagsmask = MATERIALFLAG_CUSTOMBLEND;
1908 trace_t trace = CL_TracePoint(point, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, true, false, NULL, true);
1909 if (trace.starttexture && (trace.starttexture->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER)))
1910 return trace.starttexture->refractive_index;
1912 return 1.333f; // water
1913 else
1914 return 1.0003f; // air
1915}
1916
1917// enumerate world rtlights and sum the overall amount of light in the world,
1918// from that we can calculate a scaling factor to fairly distribute photons
1919// to all the lights
1920//
1921// this modifies rtlight->photoncolor and rtlight->photons
1923{
1924 // get the range of light numbers we'll be looping over:
1925 // range = static lights
1926 // range1 = dynamic lights (optional)
1927 // range2 = range + range1
1928 unsigned int range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
1930 unsigned int range2 = range + range1;
1932
1933 float normalphotonscaling;
1934 float photonscaling;
1935 float photonintensity;
1936 float photoncount = 0.0f;
1937 float lightintensity;
1938 float radius;
1939 float s;
1940 float w;
1941 vec3_t cullmins;
1942 vec3_t cullmaxs;
1943 unsigned int lightindex;
1944 dlight_t *light;
1945 rtlight_t *rtlight;
1946 int shootparticles;
1947 int shotparticles;
1948 float bounceminimumintensity2;
1949 float startrefractiveindex;
1950 unsigned int seed;
1951 randomseed_t randomseed;
1952 vec3_t baseshotcolor;
1953
1954 normalphotonscaling = 1.0f / max(0.0000001f, r_shadow_bouncegrid_state.settings.energyperphoton);
1955 for (lightindex = 0;lightindex < range2;lightindex++)
1956 {
1957 if (lightindex < range)
1958 {
1960 if (!light)
1961 continue;
1962 rtlight = &light->rtlight;
1964 rtlight->bouncegrid_photons = 0;
1965 rtlight->bouncegrid_hits = 0;
1966 rtlight->bouncegrid_traces = 0;
1967 rtlight->bouncegrid_effectiveradius = 0;
1968 if (!(light->flags & flag))
1969 continue;
1971 {
1972 // when static, we skip styled lights because they tend to change...
1973 if (rtlight->style > 0 && r_shadow_bouncegrid.integer != 2)
1974 continue;
1975 }
1976 else if (r_shadow_debuglight.integer >= 0 && (int)lightindex != r_shadow_debuglight.integer)
1977 continue;
1978 }
1979 else
1980 {
1981 rtlight = r_refdef.scene.lights[lightindex - range];
1983 rtlight->bouncegrid_photons = 0;
1984 rtlight->bouncegrid_hits = 0;
1985 rtlight->bouncegrid_traces = 0;
1986 rtlight->bouncegrid_effectiveradius = 0;
1987 }
1988 // draw only visible lights (major speedup)
1990 cullmins[0] = rtlight->shadoworigin[0] - radius;
1991 cullmins[1] = rtlight->shadoworigin[1] - radius;
1992 cullmins[2] = rtlight->shadoworigin[2] - radius;
1993 cullmaxs[0] = rtlight->shadoworigin[0] + radius;
1994 cullmaxs[1] = rtlight->shadoworigin[1] + radius;
1995 cullmaxs[2] = rtlight->shadoworigin[2] + radius;
1996 w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
1998 {
1999 // skip if the expanded light box does not touch any visible leafs
2003 continue;
2004 // skip if the expanded light box is not visible to traceline
2005 // note that PrepareLight already did this check but for a smaller box, so we
2006 // end up casting more traces per frame per light when using bouncegrid, which
2007 // is probably fine (and they use the same timer)
2009 {
2011 rtlight->trace_timer = host.realtime;
2013 continue;
2014 }
2015 // skip if expanded light box is offscreen
2016 if (R_CullFrustum(cullmins, cullmaxs))
2017 continue;
2018 // skip if overall light intensity is zero
2019 if (w * VectorLength2(rtlight->color) == 0.0f)
2020 continue;
2021 }
2022 // a light that does not emit any light before style is applied, can be
2023 // skipped entirely (it may just be a corona)
2024 if (rtlight->radius == 0.0f || VectorLength2(rtlight->color) == 0.0f)
2025 continue;
2026 w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
2027 VectorScale(rtlight->color, w, rtlight->bouncegrid_photoncolor);
2028 // skip lights that will emit no photons
2030 continue;
2031 // shoot particles from this light
2032 // use a calculation for the number of particles that will not
2033 // vary with lightstyle, otherwise we get randomized particle
2034 // distribution, the seeded random is only consistent for a
2035 // consistent number of particles on this light...
2036 s = rtlight->radius;
2037 lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
2038 if (lightindex >= range)
2040 rtlight->bouncegrid_photons = lightintensity * s * s * normalphotonscaling;
2041 photoncount += rtlight->bouncegrid_photons;
2043 // if the lightstyle happens to be off right now, we can skip actually
2044 // firing the photons, but we did have to count them in the total.
2045 //if (VectorLength2(rtlight->photoncolor) == 0.0f)
2046 // rtlight->bouncegrid_photons = 0;
2047 }
2048 // the user provided an energyperphoton value which we try to use
2049 // if that results in too many photons to shoot this frame, then we cap it
2050 // which causes photons to appear/disappear from frame to frame, so we don't
2051 // like doing that in the typical case
2052 photonscaling = 1.0f;
2053 photonintensity = 1.0f;
2055 {
2056 photonscaling = r_shadow_bouncegrid_state.settings.maxphotons / photoncount;
2057 photonintensity = 1.0f / photonscaling;
2058 }
2059
2060 // modify the lights to reflect our computed scaling
2061 for (lightindex = 0; lightindex < range2; lightindex++)
2062 {
2063 if (lightindex < range)
2064 {
2066 if (!light)
2067 continue;
2068 rtlight = &light->rtlight;
2069 }
2070 else
2071 rtlight = r_refdef.scene.lights[lightindex - range];
2072 rtlight->bouncegrid_photons *= photonscaling;
2073 VectorScale(rtlight->bouncegrid_photoncolor, photonintensity, rtlight->bouncegrid_photoncolor);
2074 }
2075
2076 // compute a seed for the unstable random modes
2077 Math_RandomSeed_FromInts(&randomseed, 0, 0, 0, host.realtime * 1000.0);
2078 seed = host.realtime * 1000.0;
2079
2080 for (lightindex = 0; lightindex < range2; lightindex++)
2081 {
2082 if (lightindex < range)
2083 {
2085 if (!light)
2086 continue;
2087 rtlight = &light->rtlight;
2088 }
2089 else
2090 rtlight = r_refdef.scene.lights[lightindex - range];
2091 // note that this code used to keep track of residual photons and
2092 // distribute them evenly to achieve exactly a desired photon count,
2093 // but that caused unwanted flickering in dynamic mode
2094 shootparticles = (int)floor(rtlight->bouncegrid_photons);
2095 // skip if we won't be shooting any photons
2096 if (!shootparticles)
2097 continue;
2099 //s = settings.particleintensity / shootparticles;
2100 //VectorScale(rtlight->bouncegrid_photoncolor, s, baseshotcolor);
2101 VectorCopy(rtlight->bouncegrid_photoncolor, baseshotcolor);
2102 if (VectorLength2(baseshotcolor) <= 0.0f)
2103 continue;
2105 r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
2106 // we stop caring about bounces once the brightness goes below this fraction of the original intensity
2107 bounceminimumintensity2 = VectorLength(baseshotcolor) * r_shadow_bouncegrid_state.settings.bounceminimumintensity2;
2108
2109 // check material at shadoworigin to see what the initial refractive index should be
2110 startrefractiveindex = R_Shadow_BounceGrid_RefractiveIndexAtPoint(rtlight->shadoworigin);
2111
2112 // for seeded random we start the RNG with the position of the light
2114 {
2115 union
2116 {
2117 unsigned int i[4];
2118 float f[4];
2119 }
2120 u;
2121 u.f[0] = rtlight->shadoworigin[0];
2122 u.f[1] = rtlight->shadoworigin[1];
2123 u.f[2] = rtlight->shadoworigin[2];
2124 u.f[3] = 1;
2126 {
2127 default:
2128 case 0:
2129 // we have to shift the seed provided by the user because the result must be odd
2130 Math_RandomSeed_FromInts(&randomseed, u.i[0], u.i[1], u.i[2], u.i[3] ^ (r_shadow_bouncegrid_state.settings.rng_seed << 1));
2131 break;
2132 case 1:
2133 seed = u.i[0] ^ u.i[1] ^ u.i[2] ^ u.i[3] ^ r_shadow_bouncegrid_state.settings.rng_seed;
2134 break;
2135 }
2136 }
2137
2138 for (shotparticles = 0; shotparticles < shootparticles && r_shadow_bouncegrid_state.numphotons < r_shadow_bouncegrid_state.settings.maxphotons; shotparticles++)
2139 {
2141 VectorCopy(baseshotcolor, p->color);
2142 VectorCopy(rtlight->shadoworigin, p->start);
2144 {
2145 default:
2146 case 0:
2147 // figure out a random direction for the initial photon to go
2148 VectorLehmerRandom(&randomseed, p->end);
2149 break;
2150 case 1:
2151 // figure out a random direction for the initial photon to go
2152 VectorCheeseRandom(seed, p->end);
2153 break;
2154 }
2155
2156 // we want a uniform distribution spherically, not merely within the sphere
2158 VectorNormalize(p->end);
2159
2160 VectorMA(p->start, radius, p->end, p->end);
2161 p->bounceminimumintensity2 = bounceminimumintensity2;
2162 p->startrefractiveindex = startrefractiveindex;
2163 p->numpaths = 0;
2164 }
2165 }
2166
2167 t->done = 1;
2168}
2169
2170static void R_Shadow_BounceGrid_Slice(int zi)
2171{
2172 float *highpixels = r_shadow_bouncegrid_state.highpixels;
2173 int xi, yi; // pixel increments
2174 float color[32] = { 0 };
2176 float iradius = 1.0f / radius;
2177 int slicemins[3], slicemaxs[3];
2178 int resolution[3];
2179 int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
2180 int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2181 int photonindex;
2183 float isamples = 1.0f / samples;
2184 float samplescolorscale = isamples * isamples * isamples;
2185
2186 // we use these a lot, so get a local copy
2188
2189 for (photonindex = 0; photonindex < r_shadow_bouncegrid_state.numphotons; photonindex++)
2190 {
2192 int pathindex;
2193 for (pathindex = 0; pathindex < photon->numpaths; pathindex++)
2194 {
2195 r_shadow_bouncegrid_photon_path_t *path = photon->paths + pathindex;
2196 float pathstart[3], pathend[3], pathmins[3], pathmaxs[3], pathdelta[3], pathdir[3], pathlength2, pathilength;
2197
2200
2201 pathmins[2] = min(pathstart[2], pathend[2]);
2202 slicemins[2] = (int)floor((pathmins[2] - radius) * r_shadow_bouncegrid_state.ispacing[2]);
2203 pathmaxs[2] = max(pathstart[2], pathend[2]);
2204 slicemaxs[2] = (int)floor((pathmaxs[2] + radius) * r_shadow_bouncegrid_state.ispacing[2] + 1);
2205
2206 // skip if the path doesn't touch this slice
2207 if (zi < slicemins[2] || zi >= slicemaxs[2])
2208 continue;
2209
2210 pathmins[0] = min(pathstart[0], pathend[0]);
2211 slicemins[0] = (int)floor((pathmins[0] - radius) * r_shadow_bouncegrid_state.ispacing[0]);
2212 slicemins[0] = max(slicemins[0], 1);
2213 pathmaxs[0] = max(pathstart[0], pathend[0]);
2214 slicemaxs[0] = (int)floor((pathmaxs[0] + radius) * r_shadow_bouncegrid_state.ispacing[0]);
2215 slicemaxs[0] = min(slicemaxs[0], resolution[0] - 1);
2216
2217 pathmins[1] = min(pathstart[1], pathend[1]);
2218 slicemins[1] = (int)floor((pathmins[1] - radius) * r_shadow_bouncegrid_state.ispacing[1] + 1);
2219 slicemins[1] = max(slicemins[1], 1);
2220 pathmaxs[1] = max(pathstart[1], pathend[1]);
2221 slicemaxs[1] = (int)floor((pathmaxs[1] + radius) * r_shadow_bouncegrid_state.ispacing[1] + 1);
2222 slicemaxs[1] = min(slicemaxs[1], resolution[1] - 1);
2223
2224 // skip if the path is out of bounds on X or Y
2225 if (slicemins[0] >= slicemaxs[0] || slicemins[1] >= slicemaxs[1])
2226 continue;
2227
2228 // calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
2229 // accumulate average shotcolor
2230 VectorSubtract(pathend, pathstart, pathdelta);
2231 pathlength2 = VectorLength2(pathdelta);
2232 pathilength = pathlength2 > 0.0f ? 1.0f / sqrt(pathlength2) : 0.0f;
2233 VectorScale(pathdelta, pathilength, pathdir);
2234 // the color is scaled by the number of subsamples
2235 color[0] = path->color[0] * samplescolorscale;
2236 color[1] = path->color[1] * samplescolorscale;
2237 color[2] = path->color[2] * samplescolorscale;
2238 color[3] = 0.0f;
2239 if (pixelbands > 1)
2240 {
2241 // store bentnormal in case the shader has a use for it,
2242 // bentnormal is an intensity-weighted average of the directions,
2243 // and will be normalized on conversion to texture pixels.
2244 float intensity = VectorLength(color);
2245 color[4] = pathdir[0] * intensity;
2246 color[5] = pathdir[1] * intensity;
2247 color[6] = pathdir[2] * intensity;
2248 color[7] = intensity;
2249 // for each color component (R, G, B) calculate the amount that a
2250 // direction contributes
2251 color[8] = color[0] * max(0.0f, pathdir[0]);
2252 color[9] = color[0] * max(0.0f, pathdir[1]);
2253 color[10] = color[0] * max(0.0f, pathdir[2]);
2254 color[11] = 0.0f;
2255 color[12] = color[1] * max(0.0f, pathdir[0]);
2256 color[13] = color[1] * max(0.0f, pathdir[1]);
2257 color[14] = color[1] * max(0.0f, pathdir[2]);
2258 color[15] = 0.0f;
2259 color[16] = color[2] * max(0.0f, pathdir[0]);
2260 color[17] = color[2] * max(0.0f, pathdir[1]);
2261 color[18] = color[2] * max(0.0f, pathdir[2]);
2262 color[19] = 0.0f;
2263 // and do the same for negative directions
2264 color[20] = color[0] * max(0.0f, -pathdir[0]);
2265 color[21] = color[0] * max(0.0f, -pathdir[1]);
2266 color[22] = color[0] * max(0.0f, -pathdir[2]);
2267 color[23] = 0.0f;
2268 color[24] = color[1] * max(0.0f, -pathdir[0]);
2269 color[25] = color[1] * max(0.0f, -pathdir[1]);
2270 color[26] = color[1] * max(0.0f, -pathdir[2]);
2271 color[27] = 0.0f;
2272 color[28] = color[2] * max(0.0f, -pathdir[0]);
2273 color[29] = color[2] * max(0.0f, -pathdir[1]);
2274 color[30] = color[2] * max(0.0f, -pathdir[2]);
2275 color[31] = 0.0f;
2276 }
2277
2278 for (yi = slicemins[1]; yi < slicemaxs[1]; yi++)
2279 {
2280 for (xi = slicemins[0]; xi < slicemaxs[0]; xi++)
2281 {
2282 float sample[3], diff[3], nearest[3], along, distance2;
2283 float *p = highpixels + 4 * ((zi * resolution[1] + yi) * resolution[0] + xi);
2284 int xs, ys, zs;
2285 // loop over the subsamples
2286 for (zs = 0; zs < samples; zs++)
2287 {
2288 sample[2] = (zi + (zs + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[2];
2289 for (ys = 0; ys < samples; ys++)
2290 {
2291 sample[1] = (yi + (ys + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[1];
2292 for (xs = 0; xs < samples; xs++)
2293 {
2294 sample[0] = (xi + (xs + 0.5f) * isamples) * r_shadow_bouncegrid_state.spacing[0];
2295
2296 // measure distance from subsample to line segment and see if it is within radius
2297 along = DotProduct(sample, pathdir) * pathilength;
2298 if (along <= 0)
2299 VectorCopy(pathstart, nearest);
2300 else if (along >= 1)
2301 VectorCopy(pathend, nearest);
2302 else
2303 VectorLerp(pathstart, along, pathend, nearest);
2304 VectorSubtract(sample, nearest, diff);
2305 VectorScale(diff, iradius, diff);
2306 distance2 = VectorLength2(diff);
2307 if (distance2 < 1.0f)
2308 {
2309 // contribute some color to this pixel, across all bands
2310 float w = 1.0f - sqrt(distance2);
2311 int band;
2312 w *= w;
2313 if (pixelbands > 1)
2314 {
2315 // small optimization for alpha - only color[7] is non-zero, so skip the rest of the alpha elements.
2316 p[pixelsperband * 4 + 3] += color[7] * w;
2317 }
2318 for (band = 0; band < pixelbands; band++)
2319 {
2320 // add to the pixel color (RGB only - see above)
2321 p[band * pixelsperband * 4 + 0] += color[band * 4 + 0] * w;
2322 p[band * pixelsperband * 4 + 1] += color[band * 4 + 1] * w;
2323 p[band * pixelsperband * 4 + 2] += color[band * 4 + 2] * w;
2324 }
2325 }
2326 }
2327 }
2328 }
2329 }
2330 }
2331 }
2332 }
2333}
2334
2336{
2337 R_Shadow_BounceGrid_Slice((int)t->i[0]);
2338 t->done = 1;
2339}
2340
2342{
2343 int i, slices;
2344 // we need to wait for the texture clear to finish before we start adding light to it
2346 {
2347 TaskQueue_Yield(t);
2348 return;
2349 }
2350 slices = r_shadow_bouncegrid_state.resolution[2] - 2;
2351 for (i = 0; i < slices; i++)
2356 t->done = 1;
2357}
2358
2359static void R_Shadow_BounceGrid_BlurPixelsInDirection(const float *inpixels, float *outpixels, int off)
2360{
2361 const float *inpixel;
2362 float *outpixel;
2363 int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2364 int pixelband;
2365 unsigned int index;
2366 unsigned int x, y, z;
2367 unsigned int resolution[3];
2369 for (pixelband = 0;pixelband < pixelbands;pixelband++)
2370 {
2371 for (z = 1;z < resolution[2]-1;z++)
2372 {
2373 for (y = 1;y < resolution[1]-1;y++)
2374 {
2375 x = 1;
2376 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2377 inpixel = inpixels + 4*index;
2378 outpixel = outpixels + 4*index;
2379 for (;x < resolution[0]-1;x++, inpixel += 4, outpixel += 4)
2380 {
2381 outpixel[0] = (inpixel[0] + inpixel[ off] + inpixel[0-off]) * (1.0f / 3.0);
2382 outpixel[1] = (inpixel[1] + inpixel[1+off] + inpixel[1-off]) * (1.0f / 3.0);
2383 outpixel[2] = (inpixel[2] + inpixel[2+off] + inpixel[2-off]) * (1.0f / 3.0);
2384 outpixel[3] = (inpixel[3] + inpixel[3+off] + inpixel[3-off]) * (1.0f / 3.0);
2385 }
2386 }
2387 }
2388 }
2389}
2390
2417
2419{
2421 unsigned char *pixelsbgra8 = NULL;
2422 unsigned char *pixelbgra8;
2423 unsigned short *pixelsrgba16f = NULL;
2424 unsigned short *pixelrgba16f;
2425 float *pixelsrgba32f = NULL;
2426 float *highpixels = r_shadow_bouncegrid_state.highpixels;
2427 float *highpixel;
2428 float *bandpixel;
2429 unsigned int pixelsperband = r_shadow_bouncegrid_state.pixelsperband;
2430 unsigned int pixelbands = r_shadow_bouncegrid_state.pixelbands;
2431 unsigned int pixelband;
2432 unsigned int x, y, z;
2433 unsigned int index, bandindex;
2434 unsigned int resolution[3];
2435 int c[4];
2437
2439 {
2442 }
2443
2444 // if bentnormals exist, we need to normalize and bias them for the shader
2445 if (pixelbands > 1)
2446 {
2447 pixelband = 1;
2448 for (z = 0;z < resolution[2]-1;z++)
2449 {
2450 for (y = 0;y < resolution[1]-1;y++)
2451 {
2452 x = 1;
2453 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2454 highpixel = highpixels + 4*index;
2455 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2456 {
2457 // only convert pixels that were hit by photons
2458 if (highpixel[3] != 0.0f)
2459 VectorNormalize(highpixel);
2460 VectorSet(highpixel, highpixel[0] * 0.5f + 0.5f, highpixel[1] * 0.5f + 0.5f, highpixel[2] * 0.5f + 0.5f);
2461 highpixel[pixelsperband * 4 + 3] = 1.0f;
2462 }
2463 }
2464 }
2465 }
2466
2467 // start by clearing the pixels array - we won't be writing to all of it
2468 //
2469 // then process only the pixels that have at least some color, skipping
2470 // the higher bands for speed on pixels that are black
2471 switch (floatcolors)
2472 {
2473 case 0:
2475 r_shadow_bouncegrid_state.u8pixels = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned char[4]));
2476 pixelsbgra8 = r_shadow_bouncegrid_state.u8pixels;
2477 for (pixelband = 0;pixelband < pixelbands;pixelband++)
2478 {
2479 if (pixelband == 1)
2480 memset(pixelsbgra8 + pixelband * r_shadow_bouncegrid_state.bytesperband, 128, r_shadow_bouncegrid_state.bytesperband);
2481 else
2483 }
2484 for (z = 1;z < resolution[2]-1;z++)
2485 {
2486 for (y = 1;y < resolution[1]-1;y++)
2487 {
2488 x = 1;
2489 pixelband = 0;
2490 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2491 highpixel = highpixels + 4*index;
2492 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2493 {
2494 // only convert pixels that were hit by photons
2495 if (VectorLength2(highpixel))
2496 {
2497 // normalize the bentnormal now
2498 if (pixelbands > 1)
2499 {
2500 VectorNormalize(highpixel + pixelsperband * 4);
2501 highpixel[pixelsperband * 4 + 3] = 1.0f;
2502 }
2503 // process all of the pixelbands for this pixel
2504 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
2505 {
2506 pixelbgra8 = pixelsbgra8 + 4*bandindex;
2507 bandpixel = highpixels + 4*bandindex;
2508 c[0] = (int)(bandpixel[0]*256.0f);
2509 c[1] = (int)(bandpixel[1]*256.0f);
2510 c[2] = (int)(bandpixel[2]*256.0f);
2511 c[3] = (int)(bandpixel[3]*256.0f);
2512 pixelbgra8[2] = (unsigned char)bound(0, c[0], 255);
2513 pixelbgra8[1] = (unsigned char)bound(0, c[1], 255);
2514 pixelbgra8[0] = (unsigned char)bound(0, c[2], 255);
2515 pixelbgra8[3] = (unsigned char)bound(0, c[3], 255);
2516 }
2517 }
2518 }
2519 }
2520 }
2521
2523 R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixelsbgra8, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
2524 else
2525 r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, pixelsbgra8, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2526 break;
2527 case 1:
2529 r_shadow_bouncegrid_state.fp16pixels = (unsigned short *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
2530 pixelsrgba16f = r_shadow_bouncegrid_state.fp16pixels;
2531 memset(pixelsrgba16f, 0, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4]));
2532 for (z = 1;z < resolution[2]-1;z++)
2533 {
2534 for (y = 1;y < resolution[1]-1;y++)
2535 {
2536 x = 1;
2537 pixelband = 0;
2538 index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
2539 highpixel = highpixels + 4*index;
2540 for (;x < resolution[0]-1;x++, index++, highpixel += 4)
2541 {
2542 // only convert pixels that were hit by photons
2543 if (VectorLength2(highpixel))
2544 {
2545 // process all of the pixelbands for this pixel
2546 for (pixelband = 0, bandindex = index;pixelband < pixelbands;pixelband++, bandindex += pixelsperband)
2547 {
2548 // time to have fun with IEEE 754 bit hacking...
2549 union {
2550 float f[4];
2551 unsigned int raw[4];
2552 } u;
2553 pixelrgba16f = pixelsrgba16f + 4*bandindex;
2554 bandpixel = highpixels + 4*bandindex;
2555 VectorCopy4(bandpixel, u.f);
2556 VectorCopy4(u.raw, c);
2557 // this math supports negative numbers, snaps denormals to zero
2558 //pixelrgba16f[0] = (unsigned short)(((c[0] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[0] - 0x38000000) >> 13) & 0x7FFF) | ((c[0] >> 16) & 0x8000));
2559 //pixelrgba16f[1] = (unsigned short)(((c[1] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[1] - 0x38000000) >> 13) & 0x7FFF) | ((c[1] >> 16) & 0x8000));
2560 //pixelrgba16f[2] = (unsigned short)(((c[2] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[2] - 0x38000000) >> 13) & 0x7FFF) | ((c[2] >> 16) & 0x8000));
2561 //pixelrgba16f[3] = (unsigned short)(((c[3] & 0x7FFFFFFF) < 0x38000000) ? 0 : (((c[3] - 0x38000000) >> 13) & 0x7FFF) | ((c[3] >> 16) & 0x8000));
2562 // this math does not support negative
2563 pixelrgba16f[0] = (unsigned short)((c[0] < 0x38000000) ? 0 : ((c[0] - 0x38000000) >> 13));
2564 pixelrgba16f[1] = (unsigned short)((c[1] < 0x38000000) ? 0 : ((c[1] - 0x38000000) >> 13));
2565 pixelrgba16f[2] = (unsigned short)((c[2] < 0x38000000) ? 0 : ((c[2] - 0x38000000) >> 13));
2566 pixelrgba16f[3] = (unsigned short)((c[3] < 0x38000000) ? 0 : ((c[3] - 0x38000000) >> 13));
2567 }
2568 }
2569 }
2570 }
2571 }
2572
2574 R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba16f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
2575 else
2576 r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba16f, TEXTYPE_COLORBUFFER16F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2577 break;
2578 case 2:
2579 // our native format happens to match, so this is easy.
2580 pixelsrgba32f = highpixels;
2581
2583 R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba32f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
2584 else
2585 r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba32f, TEXTYPE_COLORBUFFER32F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
2586 break;
2587 }
2588
2590}
2591
2593{
2595 t->done = 1;
2596}
2597
2598static void R_Shadow_BounceGrid_TracePhotons_Shot(r_shadow_bouncegrid_photon_t *p, int remainingbounces, vec3_t shotstart, vec3_t shotend, vec3_t shotcolor, float bounceminimumintensity2, float previousrefractiveindex)
2599{
2600 int hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask;
2601 vec3_t shothit;
2602 vec3_t surfacenormal;
2603 vec3_t reflectstart, reflectend, reflectcolor;
2604 vec3_t refractstart, refractend, refractcolor;
2605 vec_t s;
2606 float reflectamount = 1.0f;
2607 trace_t cliptrace;
2608 // figure out what we want to interact with
2609 hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK;
2610 skipsupercontentsmask = 0;
2611 skipmaterialflagsmask = MATERIALFLAG_CUSTOMBLEND;
2612 //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
2613 //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
2615 {
2616 // static mode fires a LOT of rays but none of them are identical, so they are not cached
2617 // non-stable random in dynamic mode also never reuses a direction, so there's no reason to cache it
2618 cliptrace = CL_TraceLine(shotstart, shotend, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, collision_extendmovelength.value, true, false, NULL, true, true);
2619 }
2620 else
2621 {
2622 // dynamic mode fires many rays and most will match the cache from the previous frame
2623 cliptrace = CL_Cache_TraceLineSurfaces(shotstart, shotend, r_shadow_bouncegrid_state.settings.staticmode ? MOVE_WORLDONLY : (r_shadow_bouncegrid_state.settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
2624 }
2625 VectorCopy(cliptrace.endpos, shothit);
2627 {
2628 qbool notculled = true;
2629 // cull paths that fail R_CullFrustum in dynamic mode
2632 {
2633 vec3_t cullmins, cullmaxs;
2634 cullmins[0] = min(shotstart[0], shothit[0]) - r_shadow_bouncegrid_state.settings.spacing[0] - r_shadow_bouncegrid_state.settings.lightpathsize;
2635 cullmins[1] = min(shotstart[1], shothit[1]) - r_shadow_bouncegrid_state.settings.spacing[1] - r_shadow_bouncegrid_state.settings.lightpathsize;
2636 cullmins[2] = min(shotstart[2], shothit[2]) - r_shadow_bouncegrid_state.settings.spacing[2] - r_shadow_bouncegrid_state.settings.lightpathsize;
2637 cullmaxs[0] = max(shotstart[0], shothit[0]) + r_shadow_bouncegrid_state.settings.spacing[0] + r_shadow_bouncegrid_state.settings.lightpathsize;
2638 cullmaxs[1] = max(shotstart[1], shothit[1]) + r_shadow_bouncegrid_state.settings.spacing[1] + r_shadow_bouncegrid_state.settings.lightpathsize;
2639 cullmaxs[2] = max(shotstart[2], shothit[2]) + r_shadow_bouncegrid_state.settings.spacing[2] + r_shadow_bouncegrid_state.settings.lightpathsize;
2640 if (R_CullFrustum(cullmins, cullmaxs))
2641 notculled = false;
2642 }
2643 if (notculled)
2644 {
2646 VectorCopy(shotstart, path->start);
2647 VectorCopy(shothit, path->end);
2648 VectorCopy(shotcolor, path->color);
2649 }
2650 }
2651 if (cliptrace.fraction < 1.0f && remainingbounces > 0)
2652 {
2653 // scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
2654 // also clamp the resulting color to never add energy, even if the user requests extreme values
2655 VectorCopy(cliptrace.plane.normal, surfacenormal);
2656 VectorSet(reflectcolor, 0.5f, 0.5f, 0.5f);
2658 // FIXME: we need to determine the exact triangle, vertex color and texcoords and texture color and texture normal for the impacted point
2659 if (cliptrace.hittexture)
2660 {
2661 if (cliptrace.hittexture->currentskinframe)
2662 VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, reflectcolor);
2663 if (cliptrace.hittexture->currentalpha < 1.0f && (cliptrace.hittexture->currentmaterialflags & (MATERIALFLAG_ALPHA | MATERIALFLAG_ALPHATEST)))
2664 {
2665 reflectamount *= cliptrace.hittexture->currentalpha;
2666 if (cliptrace.hittexture->currentskinframe)
2667 reflectamount *= cliptrace.hittexture->currentskinframe->avgcolor[3];
2668 }
2669 if (cliptrace.hittexture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2670 {
2671 float Fresnel;
2672 vec3_t lightdir;
2673 //reflectchance = pow(min(1.0f, 1.0f - cliptrace.
2674 VectorSubtract(shotstart, shotend, lightdir);
2675 VectorNormalize(lightdir);
2676 Fresnel = min(1.0f, 1.0f - DotProduct(lightdir, surfacenormal));
2677 Fresnel = Fresnel * Fresnel * (cliptrace.hittexture->reflectmax - cliptrace.hittexture->reflectmin) + cliptrace.hittexture->reflectmin;
2678 reflectamount *= Fresnel;
2679 VectorCopy(cliptrace.hittexture->refractcolor4f, refractcolor);
2680 }
2681 if (cliptrace.hittexture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2682 VectorCopy(cliptrace.hittexture->refractcolor4f, refractcolor);
2683 // make sure we do not gain energy even if surface colors are out of bounds
2684 reflectcolor[0] = min(reflectcolor[0], 1.0f);
2685 reflectcolor[1] = min(reflectcolor[1], 1.0f);
2686 reflectcolor[2] = min(reflectcolor[2], 1.0f);
2687 refractcolor[0] = min(refractcolor[0], 1.0f);
2688 refractcolor[1] = min(refractcolor[1], 1.0f);
2689 refractcolor[2] = min(refractcolor[2], 1.0f);
2690 }
2691 // reflected and refracted shots
2692 VectorScale(reflectcolor, r_shadow_bouncegrid_state.settings.particlebounceintensity * reflectamount, reflectcolor);
2693 VectorScale(refractcolor, (1.0f - reflectamount), refractcolor);
2694 VectorMultiply(reflectcolor, shotcolor, reflectcolor);
2696
2697 if (VectorLength2(reflectcolor) >= bounceminimumintensity2)
2698 {
2699 // reflect the remaining portion of the line across plane normal
2700 VectorSubtract(shotend, shothit, reflectend);
2701 VectorReflect(reflectend, 1.0, surfacenormal, reflectend);
2702 // calculate the new line start and end
2703 VectorCopy(shothit, reflectstart);
2704 VectorAdd(reflectstart, reflectend, reflectend);
2705 R_Shadow_BounceGrid_TracePhotons_Shot(p, remainingbounces - 1, reflectstart, reflectend, reflectcolor, bounceminimumintensity2, previousrefractiveindex);
2706 }
2707
2708 if (VectorLength2(refractcolor) >= bounceminimumintensity2)
2709 {
2710 // Check what refractive index is on the other side
2711 float refractiveindex;
2712 VectorMA(shothit, 0.0625f, cliptrace.plane.normal, refractstart);
2713 refractiveindex = R_Shadow_BounceGrid_RefractiveIndexAtPoint(refractstart);
2714 // reflect the remaining portion of the line across plane normal
2715 VectorSubtract(shotend, shothit, refractend);
2716 s = refractiveindex / previousrefractiveindex;
2717 VectorReflect(refractend, -1.0f / s, surfacenormal, refractend);
2718 // we also need to reflect the start to the other side of the plane so it doesn't just hit the same surface again
2719 // calculate the new line start and end
2720 VectorMA(shothit, 0.0625f, cliptrace.plane.normal, refractstart);
2721 VectorAdd(refractstart, refractend, refractend);
2722 R_Shadow_BounceGrid_TracePhotons_Shot(p, remainingbounces - 1, refractstart, refractend, refractcolor, bounceminimumintensity2, refractiveindex);
2723 }
2724 }
2725}
2726
2733
2754
2756{
2759 qbool enable = false;
2760 qbool settingschanged;
2761
2762 enable = R_Shadow_BounceGrid_CheckEnable(flag);
2763
2765
2766 // changing intensity does not require an update
2768
2769 settingschanged = memcmp(&r_shadow_bouncegrid_state.settings, &settings, sizeof(settings)) != 0;
2770
2771 // when settings change, we free everything as it is just simpler that way.
2772 if (settingschanged || !enable)
2773 {
2774 // not enabled, make sure we free anything we don't need anymore.
2776 {
2779 }
2784
2785 if (!enable)
2786 return;
2787 }
2788
2789 // if all the settings seem identical to the previous update, return
2791 return;
2792
2793 // store the new settings
2795
2797
2798 // allocate the highpixels array we'll be accumulating light into
2805
2806 // set up the tracking of photon data
2812
2813 // set up the tracking of slice tasks
2816
2826
2827 // clear the texture
2830
2831 // calculate weighting factors for distributing photons among the lights
2834
2835 // enqueue tasks to trace the photons from lights
2838
2839 // accumulate the light paths into texture
2842
2843 // apply a mild blur filter to the texture
2846
2848 R_TimeReport("bouncegrid_gen");
2849
2850 // convert the pixels to lower precision and upload the texture
2851 // this unfortunately has to run on the main thread for OpenGL calls, so we have to block on the previous task...
2853 R_TimeReport("bouncegrid_tex");
2854
2855 // after we compute the static lighting we don't need to keep the highpixels array around
2856 if (settings.staticmode)
2858}
2859
2871
2880
2881int bboxedges[12][2] =
2882{
2883 // top
2884 {0, 1}, // +X
2885 {0, 2}, // +Y
2886 {1, 3}, // Y, +X
2887 {2, 3}, // X, +Y
2888 // bottom
2889 {4, 5}, // +X
2890 {4, 6}, // +Y
2891 {5, 7}, // Y, +X
2892 {6, 7}, // X, +Y
2893 // verticals
2894 {0, 4}, // +Z
2895 {1, 5}, // X, +Z
2896 {2, 6}, // Y, +Z
2897 {3, 7}, // XY, +Z
2898};
2899
2919
2920static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2921{
2922 // used to display how many times a surface is lit for level design purposes
2923 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
2926}
2927
2928static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3])
2929{
2930 // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2931 R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false, false);
2933}
2934
2935extern cvar_t gl_lightmaps;
2936void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2937{
2938 qbool negated;
2939 float ambientcolor[3], diffusecolor[3], specularcolor[3];
2944 {
2945 VectorMAM(1.0f, ambientcolor, 1.0f, diffusecolor, ambientcolor);
2946 VectorClear(diffusecolor);
2947 VectorClear(specularcolor);
2948 }
2949 VectorMultiply(ambientcolor, rsurface.rtlight->currentcolor, ambientcolor);
2950 VectorMultiply(diffusecolor, rsurface.rtlight->currentcolor, diffusecolor);
2951 VectorMultiply(specularcolor, rsurface.rtlight->currentcolor, specularcolor);
2952 if (VectorLength2(ambientcolor) + VectorLength2(diffusecolor) + VectorLength2(specularcolor) < (1.0f / 1048576.0f))
2953 return;
2955 if(negated)
2956 {
2957 VectorNegate(ambientcolor, ambientcolor);
2958 VectorNegate(diffusecolor, diffusecolor);
2959 VectorNegate(specularcolor, specularcolor);
2961 }
2963 switch (r_shadow_rendermode)
2964 {
2967 R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
2968 break;
2970 R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor, specularcolor);
2971 break;
2972 default:
2973 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2974 break;
2975 }
2976 if(negated)
2978}
2979
2980void 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)
2981{
2982 matrix4x4_t tempmatrix = *matrix;
2984
2985 // if this light has been compiled before, free the associated data
2986 R_RTLight_Uncompile(rtlight);
2987
2988 // clear it completely to avoid any lingering data
2989 memset(rtlight, 0, sizeof(*rtlight));
2990
2991 // copy the properties
2992 rtlight->matrix_lighttoworld = tempmatrix;
2993 Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
2994 Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
2995 rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
2996 VectorCopy(color, rtlight->color);
2997 rtlight->cubemapname[0] = 0;
2998 if (cubemapname && cubemapname[0])
2999 dp_strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
3000 rtlight->shadow = shadow;
3001 rtlight->corona = corona;
3002 rtlight->style = style;
3003 rtlight->isstatic = isstatic;
3004 rtlight->coronasizescale = coronasizescale;
3005 rtlight->ambientscale = ambientscale;
3006 rtlight->diffusescale = diffusescale;
3007 rtlight->specularscale = specularscale;
3008 rtlight->flags = flags;
3009
3010 // compute derived data
3011 //rtlight->cullradius = rtlight->radius;
3012 //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
3013 rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3014 rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3015 rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3016 rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3017 rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3018 rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3019}
3020
3021// compiles rtlight geometry
3022// (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
3024{
3025 int i;
3026 int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
3027 int lighttris, shadowtris;
3030 unsigned char *data;
3031
3032 // compile the light
3033 rtlight->compiled = true;
3034 rtlight->static_numleafs = 0;
3035 rtlight->static_numleafpvsbytes = 0;
3036 rtlight->static_leaflist = NULL;
3037 rtlight->static_leafpvs = NULL;
3038 rtlight->static_numsurfaces = 0;
3039 rtlight->static_surfacelist = NULL;
3040 rtlight->static_shadowmap_receivers = 0x3F;
3041 rtlight->static_shadowmap_casters = 0x3F;
3042 rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3043 rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3044 rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3045 rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3046 rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3047 rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3048
3049 if (model && model->GetLightInfo)
3050 {
3051 // this variable must be set for the CompileShadowMap code
3052 r_shadow_compilingrtlight = rtlight;
3056 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
3057 numshadowtrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
3058 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
3059 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
3060 rtlight->static_numsurfaces = numsurfaces;
3061 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
3062 rtlight->static_numleafs = numleafs;
3063 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
3064 rtlight->static_numleafpvsbytes = numleafpvsbytes;
3065 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
3066 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
3067 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
3068 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
3069 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
3070 if (rtlight->static_numsurfaces)
3071 memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
3072 if (rtlight->static_numleafs)
3073 memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3074 if (rtlight->static_numleafpvsbytes)
3076 if (rtlight->static_numshadowtrispvsbytes)
3078 if (rtlight->static_numlighttrispvsbytes)
3081 if (model->CompileShadowMap && rtlight->shadow)
3082 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3084 // now we're done compiling the rtlight
3086 }
3087
3088
3089 // use smallest available cullradius - box radius or light radius
3090 //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
3091 //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
3092
3093 lighttris = 0;
3094 if (rtlight->static_numlighttrispvsbytes)
3095 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
3096 if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
3097 lighttris++;
3098
3099 shadowtris = 0;
3100 if (rtlight->static_numshadowtrispvsbytes)
3101 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
3102 if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
3103 shadowtris++;
3104
3106 Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris);
3107}
3108
3110{
3111 if (rtlight->compiled)
3112 {
3116 // these allocations are grouped
3117 if (rtlight->static_surfacelist)
3118 Mem_Free(rtlight->static_surfacelist);
3119 rtlight->static_numleafs = 0;
3120 rtlight->static_numleafpvsbytes = 0;
3121 rtlight->static_leaflist = NULL;
3122 rtlight->static_leafpvs = NULL;
3123 rtlight->static_numsurfaces = 0;
3124 rtlight->static_surfacelist = NULL;
3125 rtlight->static_numshadowtrispvsbytes = 0;
3126 rtlight->static_shadowtrispvs = NULL;
3127 rtlight->static_numlighttrispvsbytes = 0;
3128 rtlight->static_lighttrispvs = NULL;
3129 rtlight->compiled = false;
3130 }
3131}
3132
3134{
3135 size_t lightindex;
3136 dlight_t *light;
3138 for (lightindex = 0;lightindex < range;lightindex++)
3139 {
3141 if (!light)
3142 continue;
3144 }
3145}
3146
3148{
3149 int i, j;
3150 mplane_t plane;
3151 // reset the count of frustum planes
3152 // see rtlight->cached_frustumplanes definition for how much this array
3153 // can hold
3154 rtlight->cached_numfrustumplanes = 0;
3155
3156 if (r_trippy.integer)
3157 return;
3158
3159 // haven't implemented a culling path for ortho rendering
3161 {
3162 // check if the light is on screen and copy the 4 planes if it is
3163 for (i = 0;i < 4;i++)
3164 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3165 break;
3166 if (i == 4)
3167 for (i = 0;i < 4;i++)
3169 return;
3170 }
3171
3172#if 1
3173 // generate a deformed frustum that includes the light origin, this is
3174 // used to cull shadow casting surfaces that can not possibly cast a
3175 // shadow onto the visible light-receiving surfaces, which can be a
3176 // performance gain
3177 //
3178 // if the light origin is onscreen the result will be 4 planes exactly
3179 // if the light origin is offscreen on only one axis the result will
3180 // be exactly 5 planes (split-side case)
3181 // if the light origin is offscreen on two axes the result will be
3182 // exactly 4 planes (stretched corner case)
3183 for (i = 0;i < 4;i++)
3184 {
3185 // quickly reject standard frustum planes that put the light
3186 // origin outside the frustum
3187 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3188 continue;
3189 // copy the plane
3191 }
3192 // if all the standard frustum planes were accepted, the light is onscreen
3193 // otherwise we need to generate some more planes below...
3194 if (rtlight->cached_numfrustumplanes < 4)
3195 {
3196 // at least one of the stock frustum planes failed, so we need to
3197 // create one or two custom planes to enclose the light origin
3198 for (i = 0;i < 4;i++)
3199 {
3200 // create a plane using the view origin and light origin, and a
3201 // single point from the frustum corner set
3203 VectorNormalize(plane.normal);
3204 plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
3205 // see if this plane is backwards and flip it if so
3206 for (j = 0;j < 4;j++)
3207 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3208 break;
3209 if (j < 4)
3210 {
3211 VectorNegate(plane.normal, plane.normal);
3212 plane.dist *= -1;
3213 // flipped plane, test again to see if it is now valid
3214 for (j = 0;j < 4;j++)
3215 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3216 break;
3217 // if the plane is still not valid, then it is dividing the
3218 // frustum and has to be rejected
3219 if (j < 4)
3220 continue;
3221 }
3222 // we have created a valid plane, compute extra info
3223 PlaneClassify(&plane);
3224 // copy the plane
3225 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3226#if 1
3227 // if we've found 5 frustum planes then we have constructed a
3228 // proper split-side case and do not need to keep searching for
3229 // planes to enclose the light origin
3230 if (rtlight->cached_numfrustumplanes == 5)
3231 break;
3232#endif
3233 }
3234 }
3235#endif
3236
3237#if 0
3238 for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
3239 {
3240 plane = rtlight->cached_frustumplanes[i];
3241 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));
3242 }
3243#endif
3244
3245#if 0
3246 // now add the light-space box planes if the light box is rotated, as any
3247 // caster outside the oriented light box is irrelevant (even if it passed
3248 // the worldspace light box, which is axial)
3249 if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
3250 {
3251 for (i = 0;i < 6;i++)
3252 {
3253 vec3_t v;
3254 VectorClear(v);
3255 v[i >> 1] = (i & 1) ? -1 : 1;
3257 VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
3258 plane.dist = VectorNormalizeLength(plane.normal);
3259 plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
3260 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3261 }
3262 }
3263#endif
3264
3265#if 0
3266 // add the world-space reduced box planes
3267 for (i = 0;i < 6;i++)
3268 {
3269 VectorClear(plane.normal);
3270 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
3271 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
3272 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3273 }
3274#endif
3275
3276#if 0
3277 {
3278 int j, oldnum;
3279 vec3_t points[8];
3280 vec_t bestdist;
3281 // reduce all plane distances to tightly fit the rtlight cull box, which
3282 // is in worldspace
3283 VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3284 VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3285 VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3286 VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3287 VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3288 VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3289 VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3290 VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3291 oldnum = rtlight->cached_numfrustumplanes;
3292 rtlight->cached_numfrustumplanes = 0;
3293 for (j = 0;j < oldnum;j++)
3294 {
3295 // find the nearest point on the box to this plane
3296 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
3297 for (i = 1;i < 8;i++)
3298 {
3299 dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
3300 if (bestdist > dist)
3301 bestdist = dist;
3302 }
3303 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);
3304 // if the nearest point is near or behind the plane, we want this
3305 // plane, otherwise the plane is useless as it won't cull anything
3306 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
3307 {
3308 PlaneClassify(&rtlight->cached_frustumplanes[j]);
3309 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
3310 }
3311 }
3312 }
3313#endif
3314}
3315
3316static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
3317{
3318 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
3319
3321 {
3324 {
3331 }
3332 }
3333 else if (r_refdef.scene.worldentity->model)
3335
3336 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
3337}
3338
3340{
3341 vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
3342 vec_t relativeshadowradius;
3343 RSurf_ActiveModelEntity(ent, false, false, false);
3344 Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
3345 // we need to re-init the shader for each entity because the matrix changed
3346 relativeshadowradius = rsurface.rtlight->radius / ent->scale;
3347 relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
3348 relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
3349 relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
3350 relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
3351 relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
3352 relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
3353 ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
3354 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
3355}
3356
3366
3367static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
3368{
3370 return;
3371
3372 // set up properties for rendering light onto this entity
3373 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
3378
3379 r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs);
3380
3381 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
3382}
3383
3385{
3386 model_t *model = ent->model;
3387 if (!model->DrawLight)
3388 return;
3389
3391
3392 model->DrawLight(ent, model->submodelsurfaces_end - model->submodelsurfaces_start, model->modelsurfaces_sorted + model->submodelsurfaces_start, NULL);
3393
3394 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
3395}
3396
3398{
3399 int i;
3400 float f;
3401 int numleafs, numsurfaces;
3402 int *leaflist, *surfacelist;
3403 unsigned char *leafpvs;
3404 unsigned char *shadowtrispvs;
3405 unsigned char *lighttrispvs;
3406 //unsigned char *surfacesides;
3407 int numlightentities;
3408 int numlightentities_noselfshadow;
3409 int numshadowentities;
3410 int numshadowentities_noselfshadow;
3411 // FIXME: bounds check lightentities and shadowentities, etc.
3412 static entity_render_t *lightentities[MAX_EDICTS];
3413 static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
3414 static entity_render_t *shadowentities[MAX_EDICTS];
3415 static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
3416 qbool nolight;
3417 qbool castshadows;
3418
3419 rtlight->draw = false;
3420 rtlight->cached_numlightentities = 0;
3422 rtlight->cached_numshadowentities = 0;
3424 rtlight->cached_numsurfaces = 0;
3425 rtlight->cached_lightentities = NULL;
3427 rtlight->cached_shadowentities = NULL;
3429 rtlight->cached_shadowtrispvs = NULL;
3430 rtlight->cached_lighttrispvs = NULL;
3431 rtlight->cached_surfacelist = NULL;
3432 rtlight->shadowmapsidesize = 0;
3433
3434 // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
3435 // skip lights that are basically invisible (color 0 0 0)
3436 nolight = VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f);
3437
3438 // loading is done before visibility checks because loading should happen
3439 // all at once at the start of a level, not when it stalls gameplay.
3440 // (especially important to benchmarks)
3441 // compile light
3442 if (rtlight->isstatic && !nolight && !rtlight->compiled && r_shadow_realtime_world_compile.integer)
3443 R_RTLight_Compile(rtlight);
3444
3445 // load cubemap
3446 rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
3447
3448 // look up the light style value at this time
3449 f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
3450 VectorScale(rtlight->color, f, rtlight->currentcolor);
3451 /*
3452 if (rtlight->selected)
3453 {
3454 f = 2 + sin(host.realtime * M_PI * 4.0);
3455 VectorScale(rtlight->currentcolor, f, rtlight->currentcolor);
3456 }
3457 */
3458
3459 // skip if lightstyle is currently off
3460 if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
3461 return;
3462
3463 // skip processing on corona-only lights
3464 if (nolight)
3465 return;
3466
3467 // skip if the light box is not touching any visible leafs
3472 return;
3473
3474 // skip if the light box is not visible to traceline
3476 {
3478 rtlight->trace_timer = host.realtime;
3480 return;
3481 }
3482
3483 // skip if the light box is off screen
3484 if (R_CullFrustum(rtlight->cullmins, rtlight->cullmaxs))
3485 return;
3486
3487 // in the typical case this will be quickly replaced by GetLightInfo
3488 VectorCopy(rtlight->cullmins, rtlight->cached_cullmins);
3489 VectorCopy(rtlight->cullmaxs, rtlight->cached_cullmaxs);
3490
3492
3493 // don't allow lights to be drawn if using r_shadow_bouncegrid 2, except if we're using static bouncegrid where dynamic lights still need to draw
3495 return;
3496
3498 {
3499 // compiled light, world available and can receive realtime lighting
3500 // retrieve leaf information
3501 numleafs = rtlight->static_numleafs;
3502 leaflist = rtlight->static_leaflist;
3503 leafpvs = rtlight->static_leafpvs;
3504 numsurfaces = rtlight->static_numsurfaces;
3505 surfacelist = rtlight->static_surfacelist;
3506 //surfacesides = NULL;
3507 shadowtrispvs = rtlight->static_shadowtrispvs;
3508 lighttrispvs = rtlight->static_lighttrispvs;
3509 }
3511 {
3512 // dynamic light, world available and can receive realtime lighting
3513 // calculate lit surfaces and leafs
3516 leaflist = r_shadow_buffer_leaflist;
3517 leafpvs = r_shadow_buffer_leafpvs;
3518 surfacelist = r_shadow_buffer_surfacelist;
3519 //surfacesides = r_shadow_buffer_surfacesides;
3520 shadowtrispvs = r_shadow_buffer_shadowtrispvs;
3521 lighttrispvs = r_shadow_buffer_lighttrispvs;
3522 // if the reduced leaf bounds are offscreen, skip it
3523 if (R_CullFrustum(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
3524 return;
3525 }
3526 else
3527 {
3528 // no world
3529 numleafs = 0;
3530 leaflist = NULL;
3531 leafpvs = NULL;
3532 numsurfaces = 0;
3533 surfacelist = NULL;
3534 //surfacesides = NULL;
3535 shadowtrispvs = NULL;
3536 lighttrispvs = NULL;
3537 }
3538 // check if light is illuminating any visible leafs
3539 if (numleafs)
3540 {
3541 for (i = 0; i < numleafs; i++)
3542 if (r_refdef.viewcache.world_leafvisible[leaflist[i]])
3543 break;
3544 if (i == numleafs)
3545 return;
3546 }
3547
3548 // make a list of lit entities and shadow casting entities
3549 numlightentities = 0;
3550 numlightentities_noselfshadow = 0;
3551 numshadowentities = 0;
3552 numshadowentities_noselfshadow = 0;
3553
3554 // add dynamic entities that are lit by the light
3555 for (i = 0; i < r_refdef.scene.numentities; i++)
3556 {
3557 model_t *model;
3559 vec3_t org;
3560 if (!BoxesOverlap(ent->mins, ent->maxs, rtlight->cached_cullmins, rtlight->cached_cullmaxs))
3561 continue;
3562 // skip the object entirely if it is not within the valid
3563 // shadow-casting region (which includes the lit region)
3564 if (R_CullBox(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
3565 continue;
3566 if (!(model = ent->model))
3567 continue;
3568 if (r_refdef.viewcache.entityvisible[i] && model->DrawLight && (ent->flags & RENDER_LIGHT))
3569 {
3570 // this entity wants to receive light, is visible, and is
3571 // inside the light box
3572 // TODO: check if the surfaces in the model can receive light
3573 // so now check if it's in a leaf seen by the light
3575 continue;
3576 if (ent->flags & RENDER_NOSELFSHADOW)
3577 lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
3578 else
3579 lightentities[numlightentities++] = ent;
3580 // since it is lit, it probably also casts a shadow...
3581 // about the VectorDistance2 - light emitting entities should not cast their own shadow
3583 if ((ent->flags & RENDER_SHADOW) && model->DrawShadowMap && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
3584 {
3585 // note: exterior models without the RENDER_NOSELFSHADOW
3586 // flag still create a RENDER_NOSELFSHADOW shadow but
3587 // are lit normally, this means that they are
3588 // self-shadowing but do not shadow other
3589 // RENDER_NOSELFSHADOW entities such as the gun
3590 // (very weird, but keeps the player shadow off the gun)
3592 shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
3593 else
3594 shadowentities[numshadowentities++] = ent;
3595 }
3596 }
3597 else if (ent->flags & RENDER_SHADOW)
3598 {
3599 // this entity is not receiving light, but may still need to
3600 // cast a shadow...
3601 // TODO: check if the surfaces in the model can cast shadow
3602 // now check if it is in a leaf seen by the light
3604 continue;
3605 // about the VectorDistance2 - light emitting entities should not cast their own shadow
3607 if ((ent->flags & RENDER_SHADOW) && model->DrawShadowMap && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
3608 {
3610 shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
3611 else
3612 shadowentities[numshadowentities++] = ent;
3613 }
3614 }
3615 }
3616
3617 // return if there's nothing at all to light
3618 if (numsurfaces + numlightentities + numlightentities_noselfshadow == 0)
3619 return;
3620
3621 // count this light in the r_speeds
3623
3624 // flag it as worth drawing later
3625 rtlight->draw = true;
3626
3627 // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one
3628 castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
3629 if (!castshadows)
3630 numshadowentities = numshadowentities_noselfshadow = 0;
3631 rtlight->castshadows = castshadows;
3632
3633 // cache all the animated entities that cast a shadow but are not visible
3634 for (i = 0; i < numshadowentities; i++)
3635 R_AnimCache_GetEntity(shadowentities[i], false, false);
3636 for (i = 0; i < numshadowentities_noselfshadow; i++)
3637 R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
3638
3639 // we can convert noselfshadow to regular if there are no receivers of that type (or we're using r_shadow_deferred which doesn't support noselfshadow anyway)
3640 if (numshadowentities_noselfshadow > 0 && (numlightentities_noselfshadow == 0 || r_shadow_usingdeferredprepass))
3641 {
3642 for (i = 0; i < numshadowentities_noselfshadow; i++)
3643 shadowentities[numshadowentities++] = shadowentities_noselfshadow[i];
3644 numshadowentities_noselfshadow = 0;
3645 }
3646
3647 // we can convert noselfshadow to regular if there are no casters of that type
3648 if (numlightentities_noselfshadow > 0 && numshadowentities_noselfshadow == 0)
3649 {
3650 for (i = 0; i < numlightentities_noselfshadow; i++)
3651 lightentities[numlightentities++] = lightentities_noselfshadow[i];
3652 numlightentities_noselfshadow = 0;
3653 }
3654
3655 // allocate some temporary memory for rendering this light later in the frame
3656 // reusable buffers need to be copied, static data can be used as-is
3657 rtlight->cached_numlightentities = numlightentities;
3658 rtlight->cached_numlightentities_noselfshadow = numlightentities_noselfshadow;
3659 rtlight->cached_numshadowentities = numshadowentities;
3660 rtlight->cached_numshadowentities_noselfshadow = numshadowentities_noselfshadow;
3661 rtlight->cached_numsurfaces = numsurfaces;
3662 rtlight->cached_lightentities = (entity_render_t**)R_FrameData_Store(numlightentities*sizeof(entity_render_t*), (void*)lightentities);
3663 rtlight->cached_lightentities_noselfshadow = (entity_render_t**)R_FrameData_Store(numlightentities_noselfshadow*sizeof(entity_render_t*), (void*)lightentities_noselfshadow);
3664 rtlight->cached_shadowentities = (entity_render_t**)R_FrameData_Store(numshadowentities*sizeof(entity_render_t*), (void*)shadowentities);
3665 rtlight->cached_shadowentities_noselfshadow = (entity_render_t**)R_FrameData_Store(numshadowentities_noselfshadow*sizeof(entity_render_t *), (void*)shadowentities_noselfshadow);
3666 if (shadowtrispvs == r_shadow_buffer_shadowtrispvs)
3667 {
3668 int numshadowtrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
3669 int numlighttrispvsbytes = ((r_refdef.scene.worldmodel->surfmesh.num_triangles + 7) >> 3);
3670 rtlight->cached_shadowtrispvs = (unsigned char *)R_FrameData_Store(numshadowtrispvsbytes, shadowtrispvs);
3671 rtlight->cached_lighttrispvs = (unsigned char *)R_FrameData_Store(numlighttrispvsbytes, lighttrispvs);
3672 rtlight->cached_surfacelist = (int*)R_FrameData_Store(numsurfaces*sizeof(int), (void*)surfacelist);
3673 }
3674 else
3675 {
3676 // compiled light data
3677 rtlight->cached_shadowtrispvs = shadowtrispvs;
3678 rtlight->cached_lighttrispvs = lighttrispvs;
3679 rtlight->cached_surfacelist = surfacelist;
3680 }
3681
3683 {
3684 // figure out the shadowmapping parameters for this light
3685 vec3_t nearestpoint;
3686 vec_t distance;
3687 int lodlinear;
3688 nearestpoint[0] = bound(rtlight->cullmins[0], r_refdef.view.origin[0], rtlight->cullmaxs[0]);
3689 nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
3690 nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
3691 distance = VectorDistance(nearestpoint, r_refdef.view.origin);
3692 lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance / rtlight->radius));
3693 //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
3696 // shadowmapatlas* variables will be set by R_Shadow_PrepareLights()
3697 }
3698}
3699
3701{
3702 int i;
3703 int numsurfaces;
3704 unsigned char *shadowtrispvs, *surfacesides;
3705 int numlightentities;
3706 int numlightentities_noselfshadow;
3707 int numshadowentities;
3708 int numshadowentities_noselfshadow;
3709 entity_render_t **lightentities;
3710 entity_render_t **lightentities_noselfshadow;
3711 entity_render_t **shadowentities;
3712 entity_render_t **shadowentities_noselfshadow;
3713 int *surfacelist;
3714 static unsigned char entitysides[MAX_EDICTS];
3715 static unsigned char entitysides_noselfshadow[MAX_EDICTS];
3716 float borderbias;
3717 int side;
3718 int size;
3719 int castermask;
3720 int receivermask;
3721 matrix4x4_t radiustolight;
3722
3723 // check if we cached this light this frame (meaning it is worth drawing)
3724 if (!rtlight->draw || !rtlight->castshadows)
3725 return;
3726
3727 // if PrepareLights could not find any space for this shadowmap, we may as well mark it as not casting shadows...
3728 if (rtlight->shadowmapatlassidesize == 0)
3729 {
3730 rtlight->castshadows = false;
3731 return;
3732 }
3733
3734 // set up a scissor rectangle for this light
3736 return;
3737
3738 numlightentities = rtlight->cached_numlightentities;
3739 numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
3740 numshadowentities = rtlight->cached_numshadowentities;
3741 numshadowentities_noselfshadow = rtlight->cached_numshadowentities_noselfshadow;
3742 numsurfaces = rtlight->cached_numsurfaces;
3743 lightentities = rtlight->cached_lightentities;
3744 lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
3745 shadowentities = rtlight->cached_shadowentities;
3746 shadowentities_noselfshadow = rtlight->cached_shadowentities_noselfshadow;
3747 shadowtrispvs = rtlight->cached_shadowtrispvs;
3748 surfacelist = rtlight->cached_surfacelist;
3749
3750 // make this the active rtlight for rendering purposes
3752
3753 radiustolight = rtlight->matrix_worldtolight;
3754 Matrix4x4_Abs(&radiustolight);
3755
3756 size = rtlight->shadowmapatlassidesize;
3758
3759 surfacesides = NULL;
3760 castermask = 0;
3761 receivermask = 0;
3762 if (numsurfaces)
3763 {
3765 {
3766 castermask = rtlight->static_shadowmap_casters;
3767 receivermask = rtlight->static_shadowmap_receivers;
3768 }
3769 else
3770 {
3771 surfacesides = r_shadow_buffer_surfacesides;
3772 for (i = 0; i < numsurfaces; i++)
3773 {
3774 msurface_t *surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[i];
3775 surfacesides[i] = R_Shadow_CalcBBoxSideMask(surface->mins, surface->maxs, &rtlight->matrix_worldtolight, &radiustolight, borderbias);
3776 castermask |= surfacesides[i];
3777 receivermask |= surfacesides[i];
3778 }
3779 }
3780 }
3781
3782 for (i = 0; i < numlightentities && receivermask < 0x3F; i++)
3783 receivermask |= R_Shadow_CalcEntitySideMask(lightentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
3784 for (i = 0; i < numlightentities_noselfshadow && receivermask < 0x3F; i++)
3785 receivermask |= R_Shadow_CalcEntitySideMask(lightentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
3786
3787 receivermask &= R_Shadow_CullFrustumSides(rtlight, size, r_shadow_shadowmapborder);
3788
3789 if (receivermask)
3790 {
3791 for (i = 0; i < numshadowentities; i++)
3792 castermask |= (entitysides[i] = R_Shadow_CalcEntitySideMask(shadowentities[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
3793 for (i = 0; i < numshadowentities_noselfshadow; i++)
3794 castermask |= (entitysides_noselfshadow[i] = R_Shadow_CalcEntitySideMask(shadowentities_noselfshadow[i], &rtlight->matrix_worldtolight, &radiustolight, borderbias));
3795 }
3796
3797 // there is no need to render shadows for sides that have no receivers...
3798 castermask &= receivermask;
3799
3800 //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
3801
3802 // render shadow casters into shadowmaps for this light
3803 for (side = 0; side < 6; side++)
3804 {
3805 int bit = 1 << side;
3806 if (castermask & bit)
3807 {
3809 if (numsurfaces)
3810 R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
3811 for (i = 0; i < numshadowentities; i++)
3812 if (entitysides[i] & bit)
3813 R_Shadow_DrawEntityShadow(shadowentities[i]);
3814 for (i = 0; i < numshadowentities_noselfshadow; i++)
3815 if (entitysides_noselfshadow[i] & bit)
3816 R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
3817 }
3818 }
3819 // additionally if there are any noselfshadow casters we have to render a second set of shadowmaps without those :(
3820 if (numshadowentities_noselfshadow)
3821 {
3822 for (side = 0; side < 6; side++)
3823 {
3824 int bit = 1 << side;
3825 if (castermask & bit)
3826 {
3828 if (numsurfaces)
3829 R_Shadow_DrawWorldShadow_ShadowMap(numsurfaces, surfacelist, shadowtrispvs, surfacesides);
3830 for (i = 0; i < numshadowentities; i++)
3831 if (entitysides[i] & bit)
3832 R_Shadow_DrawEntityShadow(shadowentities[i]);
3833 }
3834 }
3835 }
3836}
3837
3838static void R_Shadow_DrawLight(rtlight_t *rtlight)
3839{
3840 int i;
3841 int numsurfaces;
3842 unsigned char *lighttrispvs;
3843 int numlightentities;
3844 int numlightentities_noselfshadow;
3845 entity_render_t **lightentities;
3846 entity_render_t **lightentities_noselfshadow;
3847 int *surfacelist;
3848 qbool castshadows;
3849
3850 // check if we cached this light this frame (meaning it is worth drawing)
3851 if (!rtlight->draw)
3852 return;
3853
3854 // set up a scissor rectangle for this light
3856 return;
3857
3858 numlightentities = rtlight->cached_numlightentities;
3859 numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
3860 numsurfaces = rtlight->cached_numsurfaces;
3861 lightentities = rtlight->cached_lightentities;
3862 lightentities_noselfshadow = rtlight->cached_lightentities_noselfshadow;
3863 lighttrispvs = rtlight->cached_lighttrispvs;
3864 surfacelist = rtlight->cached_surfacelist;
3865 castshadows = rtlight->castshadows;
3866
3867 // make this the active rtlight for rendering purposes
3869
3870 if (r_showlighting.integer && r_refdef.view.showdebug && numsurfaces + numlightentities + numlightentities_noselfshadow)
3871 {
3872 // optionally draw the illuminated areas
3873 // for performance analysis by level designers
3875 if (numsurfaces)
3876 R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3877 for (i = 0;i < numlightentities;i++)
3878 R_Shadow_DrawEntityLight(lightentities[i]);
3879 for (i = 0;i < numlightentities_noselfshadow;i++)
3880 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3881 }
3882
3884 {
3885 matrix4x4_t radiustolight = rtlight->matrix_worldtolight;
3886 Matrix4x4_Abs(&radiustolight);
3887
3888 //Con_Printf("distance %f lodlinear %i size %i\n", distance, lodlinear, size);
3889
3890 // render lighting using the depth texture as shadowmap
3891 // draw lighting in the unmasked areas
3892 if (numsurfaces + numlightentities)
3893 {
3894 R_Shadow_RenderMode_Lighting(false, true, false);
3895 // draw lighting in the unmasked areas
3896 if (numsurfaces)
3897 R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3898 for (i = 0; i < numlightentities; i++)
3899 R_Shadow_DrawEntityLight(lightentities[i]);
3900 }
3901 // offset to the noselfshadow part of the atlas and draw those too
3902 if (numlightentities_noselfshadow)
3903 {
3904 R_Shadow_RenderMode_Lighting(false, true, true);
3905 for (i = 0; i < numlightentities_noselfshadow; i++)
3906 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3907 }
3908
3909 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
3912 }
3913 else
3914 {
3915 // draw lighting in the unmasked areas
3916 R_Shadow_RenderMode_Lighting(false, false, false);
3917 if (numsurfaces)
3918 R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
3919 for (i = 0;i < numlightentities;i++)
3920 R_Shadow_DrawEntityLight(lightentities[i]);
3921 for (i = 0;i < numlightentities_noselfshadow;i++)
3922 R_Shadow_DrawEntityLight(lightentities_noselfshadow[i]);
3923
3924 // rasterize the box when rendering deferred lighting - the regular surface lighting only applies to transparent surfaces
3927 }
3928}
3929
3957
3959{
3960 int i;
3961 int lnum;
3962 entity_render_t *ent;
3963 float clearcolor[4];
3964
3966 GL_DepthMask(true);
3967 GL_ColorMask(1,1,1,1);
3969 GL_Color(1,1,1,1);
3970 GL_DepthTest(true);
3972 Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
3973 GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
3975 R_TimeReport("prepasscleargeom");
3976
3980 R_TimeReport("prepassworld");
3981
3982 for (i = 0;i < r_refdef.scene.numentities;i++)
3983 {
3985 continue;
3986 ent = r_refdef.scene.entities[i];
3987 if (ent->model && ent->model->DrawPrepass != NULL)
3988 ent->model->DrawPrepass(ent);
3989 }
3990
3992 R_TimeReport("prepassmodels");
3993
3994 GL_DepthMask(false);
3995 GL_ColorMask(1,1,1,1);
3996 GL_Color(1,1,1,1);
3997 GL_DepthTest(true);
3999 Vector4Set(clearcolor, 0, 0, 0, 0);
4000 GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
4002 R_TimeReport("prepassclearlit");
4003
4005
4006 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
4008
4010
4012 R_TimeReport("prepasslights");
4013}
4014
4015#define MAX_SCENELIGHTS 65536
4029
4030void R_Shadow_DrawLightSprites(void);
4032{
4033 int flag;
4034 int lnum;
4035 size_t lightindex;
4036 dlight_t *light;
4037 size_t range;
4038 float f;
4039
4040 int shadowmapborder = bound(1, r_shadow_shadowmapping_bordersize.integer, 16);
4041 int shadowmaptexturesize = bound(256, r_shadow_shadowmapping_texturesize.integer, (int)vid.maxtexturesize_2d);
4042 int shadowmapmaxsize = bound(shadowmapborder+2, r_shadow_shadowmapping_maxsize.integer, shadowmaptexturesize / 8);
4043
4046 r_shadow_shadowmaptexturesize != shadowmaptexturesize ||
4051 r_shadow_shadowmapborder != shadowmapborder ||
4052 r_shadow_shadowmapmaxsize != shadowmapmaxsize ||
4055
4057
4058 switch (vid.renderpath)
4059 {
4060 case RENDERPATH_GL32:
4061#ifndef USE_GLES2
4063 {
4068 break;
4069 }
4070
4072 {
4074
4082
4083 // set up the geometry pass fbo (depth + normalmap)
4086 // render depth into a renderbuffer and other important properties into the normalmap texture
4087
4088 // set up the lighting pass fbo (diffuse + specular)
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
4095 // set up the lighting pass fbo (diffuse)
4098 // render diffuse into one texture,
4099 // with depth and normalmap bound as textures,
4100 // with depth bound as attachment as well
4101 }
4102#endif
4103 break;
4104 case RENDERPATH_GLES2:
4106 break;
4107 }
4108
4110
4114 for (lightindex = 0; lightindex < range; lightindex++)
4115 {
4117 if (light && (light->flags & flag))
4118 {
4121 }
4122 }
4124 {
4125 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
4126 {
4129 }
4130 }
4131 else if (gl_flashblend.integer)
4132 {
4133 for (lnum = 0; lnum < r_refdef.scene.numlights; lnum++)
4134 {
4135 rtlight_t *rtlight = r_refdef.scene.lights[lnum];
4136 f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
4137 VectorScale(rtlight->color, f, rtlight->currentcolor);
4138 }
4139 }
4140
4141 // when debugging a single light, we still want to run the prepare, so we only replace the light list afterward...
4143 {
4145 lightindex = r_shadow_debuglight.integer;
4147 if (light)
4148 {
4151 }
4152 }
4153
4154 // if we're doing shadowmaps we need to prepare the atlas layout now
4156 {
4157 int lod;
4158
4159 // allocate shadowmaps in the atlas now
4160 // we may have to make multiple attempts to fit the shadowmaps in the limited space of the atlas, this will appear as lod popping of all shadowmaps whenever it changes, but at least we can still cast shadows from all lights...
4161 for (lod = 0; lod < 16; lod++)
4162 {
4163 int packing_success = 0;
4164 int packing_failure = 0;
4166 // we actually have to reserve space for the R_DrawModelShadowMaps if that feature is active, it uses 0,0 so this is easy.
4169 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
4170 {
4171 rtlight_t *rtlight = r_shadow_scenelightlist[lnum];
4172 int size = rtlight->shadowmapsidesize >> lod;
4173 int width, height;
4174 if (!rtlight->castshadows)
4175 continue;
4177 width = size * 2;
4178 height = size * 3;
4179 // when there are noselfshadow entities in the light bounds, we have to render two separate sets of shadowmaps :(
4181 width *= 2;
4183 {
4184 rtlight->shadowmapatlassidesize = size;
4185 packing_success++;
4186 }
4187 else
4188 {
4189 // note down that we failed to pack this one, it will have to disable shadows
4190 rtlight->shadowmapatlassidesize = 0;
4191 packing_failure++;
4192 }
4193 }
4194 // generally everything fits and we stop here on the first iteration
4195 if (packing_failure == 0)
4196 break;
4197 }
4198 }
4199
4202}
4203
4205{
4208
4209 // now that we have a layout of shadowmaps in the atlas, we can render the shadowmaps
4211
4212 // render model shadowmaps (r_shadows 2) if desired which will be sampled in the forward pass
4215
4217 {
4218 int lnum;
4219 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
4221 }
4222
4224}
4225
4227{
4228 int lnum;
4229
4231
4232 for (lnum = 0; lnum < r_shadow_scenenumlights; lnum++)
4234
4236}
4237
4238#define MAX_MODELSHADOWS 1024
4241
4243{
4244 int i;
4245 float scale, size, radius, dot1, dot2;
4246 prvm_vec3_t prvmshadowdir, prvmshadowfocus;
4247 vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
4248 entity_render_t *ent;
4249
4252
4254 return;
4255
4258 radius = 0.5f * size / scale;
4259
4261 VectorCopy(prvmshadowdir, shadowdir);
4262 VectorNormalize(shadowdir);
4263 dot1 = DotProduct(r_refdef.view.forward, shadowdir);
4264 dot2 = DotProduct(r_refdef.view.up, shadowdir);
4265 if (fabs(dot1) <= fabs(dot2))
4266 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
4267 else
4268 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
4269 VectorNormalize(shadowforward);
4270 CrossProduct(shadowdir, shadowforward, shadowright);
4271 Math_atov(r_shadows_focus.string, prvmshadowfocus);
4272 VectorCopy(prvmshadowfocus, shadowfocus);
4273 VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
4274 VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
4275 VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
4276 VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
4277 if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
4278 dot1 = 1;
4279 VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
4280
4281 shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
4282 shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
4283 shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
4284 shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
4285 shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
4286 shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2]));
4287
4288 for (i = 0; i < r_refdef.scene.numentities; i++)
4289 {
4290 ent = r_refdef.scene.entities[i];
4291 if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
4292 continue;
4293 // cast shadows from anything of the map (submodels are optional)
4294 if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
4295 {
4297 break;
4299 R_AnimCache_GetEntity(ent, false, false);
4300 }
4301 }
4302
4304 {
4308 }
4309}
4310
4312{
4313 int i;
4314 float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
4315 entity_render_t *ent;
4316 vec3_t relativelightorigin;
4317 vec3_t relativelightdirection, relativeforward, relativeright;
4318 vec3_t relativeshadowmins, relativeshadowmaxs;
4319 vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
4320 prvm_vec3_t prvmshadowdir, prvmshadowfocus;
4321 float m[12];
4322 matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
4323 r_viewport_t viewport;
4324
4327 radius = 0.5f / scale;
4328 nearclip = -r_shadows_throwdistance.value;
4331
4332 // set the parameters that will be used on the regular model renders using these shadows we're about to produce
4342
4344 VectorCopy(prvmshadowdir, shadowdir);
4345 VectorNormalize(shadowdir);
4346 Math_atov(r_shadows_focus.string, prvmshadowfocus);
4347 VectorCopy(prvmshadowfocus, shadowfocus);
4348 VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
4349 VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
4350 VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
4351 VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
4352 dot1 = DotProduct(r_refdef.view.forward, shadowdir);
4353 dot2 = DotProduct(r_refdef.view.up, shadowdir);
4354 if (fabs(dot1) <= fabs(dot2))
4355 VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
4356 else
4357 VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
4358 VectorNormalize(shadowforward);
4359 VectorM(scale, shadowforward, &m[0]);
4360 if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
4361 dot1 = 1;
4362 m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
4363 CrossProduct(shadowdir, shadowforward, shadowright);
4364 VectorM(scale, shadowright, &m[4]);
4365 m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
4366 VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
4367 m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
4368 Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
4369 Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
4371 R_SetViewport(&viewport);
4372
4373 VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
4374
4375 // render into a slightly restricted region so that the borders of the
4376 // shadowmap area fade away, rather than streaking across everything
4377 // outside the usable area
4379
4380 for (i = 0;i < r_shadow_nummodelshadows;i++)
4381 {
4382 ent = r_shadow_modelshadows[i];
4384 Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
4385 Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
4386 Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
4387 Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
4388 relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
4389 relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
4390 relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
4391 relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
4392 relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
4393 relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
4394 RSurf_ActiveModelEntity(ent, false, false, false);
4395 ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
4396 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
4397 }
4398
4399#if 0
4400 if (r_test.integer)
4401 {
4402 unsigned char *rawpixels = Z_Malloc(viewport.width*viewport.height*4);
4404 qglReadPixels(viewport.x, viewport.y, viewport.width, viewport.height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, rawpixels);
4406 Image_WriteTGABGRA("r_shadows_2.tga", viewport.width, viewport.height, rawpixels);
4408 Z_Free(rawpixels);
4409 }
4410#endif
4411
4413 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
4414 Matrix4x4_CreateScale3(&scalematrix, size, -size, 1);
4415 Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
4416 Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
4417 Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
4418}
4419
4420static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qbool usequery)
4421{
4422 float zdist;
4423 vec3_t centerorigin;
4424#ifndef USE_GLES2
4425 float vertex3f[12];
4426#endif
4427 // if it's too close, skip it
4428 if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
4429 return;
4431 if (zdist < 32)
4432 return;
4433 if (usequery && r_numqueries + 2 <= r_maxqueries)
4434 {
4437 // 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
4438 VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
4439
4440 switch(vid.renderpath)
4441 {
4442 case RENDERPATH_GL32:
4443 case RENDERPATH_GLES2:
4444#ifndef USE_GLES2
4446 // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
4447 qglBeginQuery(GL_SAMPLES_PASSED, rtlight->corona_queryindex_allpixels);
4449 R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
4450 R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
4452 qglEndQuery(GL_SAMPLES_PASSED);
4454 qglBeginQuery(GL_SAMPLES_PASSED, rtlight->corona_queryindex_visiblepixels);
4456 R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
4458 qglEndQuery(GL_SAMPLES_PASSED);
4460#endif
4461 break;
4462 }
4463 }
4464 rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
4465}
4466
4467static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4468
4469static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
4470{
4471 vec3_t color;
4472 unsigned int occlude = 0;
4473
4474 // now we have to check the query result
4476 {
4477 switch(vid.renderpath)
4478 {
4479 case RENDERPATH_GL32:
4480 case RENDERPATH_GLES2:
4481#ifndef USE_GLES2
4482 // store the pixel counts into a uniform buffer for the shader to
4483 // use - we'll never know the results on the cpu without
4484 // synchronizing and we don't want that
4485#define BUFFER_OFFSET(i) ((GLint *)((unsigned char*)NULL + (i)))
4487 qglGenBuffers(1, &r_shadow_occlusion_buf);
4489 qglBufferData(GL_QUERY_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
4490 } else {
4492 }
4493 qglGetQueryObjectiv(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT, BUFFER_OFFSET(0));
4494 qglGetQueryObjectiv(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT, BUFFER_OFFSET(4));
4495 qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
4496 occlude = MATERIALFLAG_OCCLUDE;
4497 cscale *= rtlight->corona_visibility;
4499 break;
4500#else
4501 return;
4502#endif
4503 }
4504 }
4505 else
4506 {
4508 return;
4509 }
4510 VectorScale(rtlight->currentcolor, cscale, color);
4511 if (VectorLength(color) > (1.0f / 256.0f))
4512 {
4513 float vertex3f[12];
4514 qbool negated = (color[0] + color[1] + color[2] < 0);
4515 if(negated)
4516 {
4519 }
4523 if(negated)
4525 }
4526}
4527
4529{
4530 int i, flag;
4531 qbool usequery = false;
4532 size_t lightindex;
4533 dlight_t *light;
4534 rtlight_t *rtlight;
4535 size_t range;
4536 if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
4537 return;
4539 return;
4542
4544
4545 // check occlusion of coronas, using occlusion queries or raytraces
4546 r_numqueries = 0;
4547 switch (vid.renderpath)
4548 {
4549 case RENDERPATH_GL32:
4550 case RENDERPATH_GLES2:
4551 // buffer binding target GL_QUERY_BUFFER: Core since version 4.4
4553#ifndef USE_GLES2
4554 if (usequery)
4555 {
4556 GL_ColorMask(0,0,0,0);
4557 if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
4559 {
4560 i = r_maxqueries;
4561 r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
4564 qglGenQueries(r_maxqueries - i, r_queries + i);
4566 }
4567 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
4570 GL_DepthMask(false);
4571 GL_DepthRange(0, 1);
4572 GL_PolygonOffset(0, 0);
4573 GL_DepthTest(true);
4575 R_SetupShader_Generic_NoTexture(false, false);
4576 }
4577#endif
4578 break;
4579 }
4580 for (lightindex = 0;lightindex < range;lightindex++)
4581 {
4583 if (!light)
4584 continue;
4585 rtlight = &light->rtlight;
4586 rtlight->corona_visibility = 0;
4588 rtlight->corona_queryindex_allpixels = 0;
4589 if (!(rtlight->flags & flag))
4590 continue;
4591 if (rtlight->corona <= 0)
4592 continue;
4593 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex)
4594 continue;
4595 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
4596 }
4597 for (i = 0;i < r_refdef.scene.numlights;i++)
4598 {
4599 rtlight = r_refdef.scene.lights[i];
4600 rtlight->corona_visibility = 0;
4602 rtlight->corona_queryindex_allpixels = 0;
4603 if (!(rtlight->flags & flag))
4604 continue;
4605 if (rtlight->corona <= 0)
4606 continue;
4607 R_BeginCoronaQuery(rtlight, rtlight->radius * rtlight->coronasizescale * r_coronas_occlusionsizescale.value, usequery);
4608 }
4609 if (usequery)
4611
4612 // now draw the coronas using the query data for intensity info
4613 for (lightindex = 0;lightindex < range;lightindex++)
4614 {
4616 if (!light)
4617 continue;
4618 rtlight = &light->rtlight;
4619 if (rtlight->corona_visibility <= 0)
4620 continue;
4621 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
4622 }
4623 for (i = 0;i < r_refdef.scene.numlights;i++)
4624 {
4625 rtlight = r_refdef.scene.lights[i];
4626 if (rtlight->corona_visibility <= 0)
4627 continue;
4628 R_DrawCorona(rtlight, rtlight->corona * r_coronas.value * 0.25f, rtlight->radius * rtlight->coronasizescale);
4629 }
4630}
4631
4632
4633
4638
4639static 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)
4640{
4641 matrix4x4_t matrix;
4642
4643 // note that style is no longer validated here, -1 is used for unstyled lights and >= MAX_LIGHTSTYLES is accepted for sake of editing rtlights files that might be out of bounds but perfectly formatted
4644
4645 // validate parameters
4646 if (!cubemapname)
4647 cubemapname = "";
4648
4649 // copy to light properties
4650 VectorCopy(origin, light->origin);
4651 light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
4652 light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
4653 light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
4654 /*
4655 light->color[0] = max(color[0], 0);
4656 light->color[1] = max(color[1], 0);
4657 light->color[2] = max(color[2], 0);
4658 */
4659 light->color[0] = color[0];
4660 light->color[1] = color[1];
4661 light->color[2] = color[2];
4662 light->radius = max(radius, 0);
4663 light->style = style;
4664 light->shadow = shadowenable;
4665 light->corona = corona;
4666 dp_strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
4667 light->coronasizescale = coronasizescale;
4668 light->ambientscale = ambientscale;
4669 light->diffusescale = diffusescale;
4670 light->specularscale = specularscale;
4671 light->flags = flags;
4672
4673 // update renderable light data
4674 Matrix4x4_CreateFromQuakeEntity(&matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], light->radius);
4675 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);
4676}
4677
4685
4687{
4688 size_t lightindex;
4689 dlight_t *light;
4691 for (lightindex = 0;lightindex < range;lightindex++)
4692 {
4694 if (light)
4696 }
4698}
4699
4708
4709static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4710{
4711 // this is never batched (there can be only one)
4712 float vertex3f[12];
4716}
4717
4718static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4719{
4720 float intensity;
4721 float s;
4722 vec3_t spritecolor;
4723 skinframe_t *skinframe;
4724 float vertex3f[12];
4725
4726 // this is never batched (due to the ent parameter changing every time)
4727 // so numsurfaces == 1 and surfacelist[0] == lightnumber
4728 const dlight_t *light = (dlight_t *)ent;
4729 s = EDLIGHTSPRSIZE;
4730
4731 R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
4732
4733 intensity = 0.5f;
4734 VectorScale(light->color, intensity, spritecolor);
4735 if (VectorLength(spritecolor) < 0.1732f)
4736 VectorSet(spritecolor, 0.1f, 0.1f, 0.1f);
4737 if (VectorLength(spritecolor) > 1.0f)
4738 VectorNormalize(spritecolor);
4739
4740 // draw light sprite
4741 if (light->cubemapname[0] && !light->shadow)
4743 else if (light->cubemapname[0])
4744 skinframe = r_editlights_sprcubemaplight;
4745 else if (!light->shadow)
4747 else
4748 skinframe = r_editlights_sprlight;
4749
4750 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);
4752
4753 // draw selection sprite if light is selected
4754 if (light->selected)
4755 {
4758 // VorteX todo: add normalmode/realtime mode light overlay sprites?
4759 }
4760}
4761
4763{
4764 size_t lightindex;
4765 dlight_t *light;
4767 for (lightindex = 0;lightindex < range;lightindex++)
4768 {
4770 if (light)
4772 }
4775}
4776
4777int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
4778{
4779 unsigned int range;
4780 dlight_t *light;
4781 rtlight_t *rtlight;
4783 if (lightindex >= range)
4784 return -1;
4786 if (!light)
4787 return 0;
4788 rtlight = &light->rtlight;
4789 //if (!(rtlight->flags & flag))
4790 // return 0;
4791 VectorCopy(rtlight->shadoworigin, origin);
4792 *radius = rtlight->radius;
4793 VectorCopy(rtlight->color, color);
4794 return 1;
4795}
4796
4798{
4799 float bestrating, rating, temp[3];
4800 dlight_t *best;
4801 size_t lightindex;
4802 dlight_t *light;
4804 best = NULL;
4805 bestrating = 0;
4806
4808 return;
4809 for (lightindex = 0;lightindex < range;lightindex++)
4810 {
4812 if (!light)
4813 continue;
4814 VectorSubtract(light->origin, r_refdef.view.origin, temp);
4815 rating = (DotProduct(temp, r_refdef.view.forward) / sqrt(DotProduct(temp, temp)));
4816 if (rating >= 0.95)
4817 {
4818 rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
4819 if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f)
4820 {
4821 bestrating = rating;
4822 best = light;
4823 }
4824 }
4825 }
4827}
4828
4830{
4831 int n, a, style, shadow, flags;
4832 char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
4833 float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
4834 if (cl.worldmodel == NULL)
4835 {
4836 Con_Print("No map loaded.\n");
4837 return;
4838 }
4839 dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
4840 lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
4841 if (lightsstring)
4842 {
4843 s = lightsstring;
4844 n = 0;
4845 while (*s)
4846 {
4847 /*
4848 t = s;
4849 shadow = true;
4850 for (;COM_Parse(t, true) && strcmp(
4851 if (COM_Parse(t, true))
4852 {
4853 if (com_token[0] == '!')
4854 {
4855 shadow = false;
4856 origin[0] = atof(com_token+1);
4857 }
4858 else
4859 origin[0] = atof(com_token);
4860 if (Com_Parse(t
4861 }
4862 */
4863 t = s;
4864 while (*s && *s != '\n' && *s != '\r')
4865 s++;
4866 if (!*s)
4867 break;
4868 tempchar = *s;
4869 shadow = true;
4870 // check for modifier flags
4871 if (*t == '!')
4872 {
4873 shadow = false;
4874 t++;
4875 }
4876 *s = 0;
4877#if _MSC_VER >= 1400
4878#define sscanf sscanf_s
4879#endif
4880 cubemapname[sizeof(cubemapname)-1] = 0;
4881#if MAX_QPATH != 128
4882#error update this code if MAX_QPATH changes
4883#endif
4884 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
4885#if _MSC_VER >= 1400
4886, (unsigned int)sizeof(cubemapname)
4887#endif
4888, &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
4889 *s = tempchar;
4890 if (a < 18)
4892 if (a < 17)
4893 specularscale = 1;
4894 if (a < 16)
4895 diffusescale = 1;
4896 if (a < 15)
4897 ambientscale = 0;
4898 if (a < 14)
4899 coronasizescale = 0.25f;
4900 if (a < 13)
4902 if (a < 10)
4903 corona = 0;
4904 if (a < 9 || !strcmp(cubemapname, "\"\""))
4905 cubemapname[0] = 0;
4906 // remove quotes on cubemapname
4907 if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
4908 {
4909 size_t namelen;
4910 namelen = strlen(cubemapname) - 2;
4911 memmove(cubemapname, cubemapname + 1, namelen);
4912 cubemapname[namelen] = '\0';
4913 }
4914 if (a < 8)
4915 {
4916 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);
4917 break;
4918 }
4919 R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
4920 if (*s == '\r')
4921 s++;
4922 if (*s == '\n')
4923 s++;
4924 n++;
4925 }
4926 if (*s)
4927 Con_Printf("invalid rtlights file \"%s\"\n", name);
4928 Mem_Free(lightsstring);
4929 }
4930}
4931
4933{
4934 size_t lightindex;
4935 dlight_t *light;
4936 size_t bufchars, bufmaxchars;
4937 char *buf, *oldbuf;
4938 char name[MAX_QPATH];
4939 char line[MAX_INPUTLINE];
4940 size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
4941 // I hate lines which are 3 times my screen size :( --blub
4942 if (!range)
4943 return;
4944 if (cl.worldmodel == NULL)
4945 {
4946 Con_Print("No map loaded.\n");
4947 return;
4948 }
4949 dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension);
4950 bufchars = bufmaxchars = 0;
4951 buf = NULL;
4952 for (lightindex = 0;lightindex < range;lightindex++)
4953 {
4955 if (!light)
4956 continue;
4957 if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE)
4958 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);
4959 else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
4960 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]);
4961 else
4962 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);
4963 if (bufchars + strlen(line) > bufmaxchars)
4964 {
4965 bufmaxchars = bufchars + strlen(line) + 2048;
4966 oldbuf = buf;
4967 buf = (char *)Mem_Alloc(tempmempool, bufmaxchars);
4968 if (oldbuf)
4969 {
4970 if (bufchars)
4971 memcpy(buf, oldbuf, bufchars);
4972 Mem_Free(oldbuf);
4973 }
4974 }
4975 if (strlen(line))
4976 {
4977 memcpy(buf + bufchars, line, strlen(line));
4978 bufchars += strlen(line);
4979 }
4980 }
4981 if (bufchars)
4982 FS_WriteFile(name, buf, (fs_offset_t)bufchars);
4983 if (buf)
4984 Mem_Free(buf);
4985}
4986
4988{
4989 int n, a, style;
4990 char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
4991 float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
4992 if (cl.worldmodel == NULL)
4993 {
4994 Con_Print("No map loaded.\n");
4995 return;
4996 }
4997 dpsnprintf(name, sizeof(name), "%s.lights", cl.worldnamenoextension);
4998 lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
4999 if (lightsstring)
5000 {
5001 s = lightsstring;
5002 n = 0;
5003 while (*s)
5004 {
5005 t = s;
5006 while (*s && *s != '\n' && *s != '\r')
5007 s++;
5008 if (!*s)
5009 break;
5010 tempchar = *s;
5011 *s = 0;
5012 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);
5013 *s = tempchar;
5014 if (a < 14)
5015 {
5016 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);
5017 break;
5018 }
5019 radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f));
5020 radius = bound(15, radius, 4096);
5021 VectorScale(color, (2.0f / (8388608.0f)), color);
5023 if (*s == '\r')
5024 s++;
5025 if (*s == '\n')
5026 s++;
5027 n++;
5028 }
5029 if (*s)
5030 Con_Printf("invalid lights file \"%s\"\n", name);
5031 Mem_Free(lightsstring);
5032 }
5033}
5034
5035// tyrlite/hmap2 light types in the delay field
5037
5039{
5040 int entnum;
5041 int style;
5042 int islight;
5043 int skin;
5044 int pflags;
5045 //int effects;
5046 int type;
5047 int n;
5048 char *entfiledata;
5049 const char *data;
5050 float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
5051 char key[256], value[MAX_INPUTLINE];
5052 char vabuf[1024];
5053
5054 if (cl.worldmodel == NULL)
5055 {
5056 Con_Print("No map loaded.\n");
5057 return;
5058 }
5059 // try to load a .ent file first
5060 dpsnprintf(key, sizeof(key), "%s.ent", cl.worldnamenoextension);
5061 data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL);
5062 // and if that is not found, fall back to the bsp file entity string
5063 if (!data)
5064 data = cl.worldmodel->brush.entities;
5065 if (!data)
5066 return;
5067 for (entnum = 0;COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{';entnum++)
5068 {
5070 origin[0] = origin[1] = origin[2] = 0;
5071 originhack[0] = originhack[1] = originhack[2] = 0;
5072 angles[0] = angles[1] = angles[2] = 0;
5073 color[0] = color[1] = color[2] = 1;
5074 light[0] = light[1] = light[2] = 1;light[3] = 300;
5075 overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
5076 fadescale = 1;
5077 lightscale = 1;
5078 style = 0;
5079 skin = 0;
5080 pflags = 0;
5081 //effects = 0;
5082 islight = false;
5083 while (1)
5084 {
5085 if (!COM_ParseToken_Simple(&data, false, false, true))
5086 break; // error
5087 if (com_token[0] == '}')
5088 break; // end of entity
5089 if (com_token[0] == '_')
5090 dp_strlcpy(key, com_token + 1, sizeof(key));
5091 else
5092 dp_strlcpy(key, com_token, sizeof(key));
5093 while (key[strlen(key)-1] == ' ') // remove trailing spaces
5094 key[strlen(key)-1] = 0;
5095 if (!COM_ParseToken_Simple(&data, false, false, true))
5096 break; // error
5097 dp_strlcpy(value, com_token, sizeof(value));
5098
5099 // now that we have the key pair worked out...
5100 if (!strcmp("light", key))
5101 {
5102 n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
5103 if (n == 1)
5104 {
5105 // quake
5106 light[0] = vec[0] * (1.0f / 256.0f);
5107 light[1] = vec[0] * (1.0f / 256.0f);
5108 light[2] = vec[0] * (1.0f / 256.0f);
5109 light[3] = vec[0];
5110 }
5111 else if (n == 4)
5112 {
5113 // halflife
5114 light[0] = vec[0] * (1.0f / 255.0f);
5115 light[1] = vec[1] * (1.0f / 255.0f);
5116 light[2] = vec[2] * (1.0f / 255.0f);
5117 light[3] = vec[3];
5118 }
5119 }
5120 else if (!strcmp("delay", key))
5121 type = atoi(value);
5122 else if (!strcmp("origin", key))
5123 sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
5124 else if (!strcmp("angle", key))
5125 angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
5126 else if (!strcmp("angles", key))
5127 sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
5128 else if (!strcmp("color", key))
5129 sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
5130 else if (!strcmp("wait", key))
5131 fadescale = atof(value);
5132 else if (!strcmp("classname", key))
5133 {
5134 if (!strncmp(value, "light", 5))
5135 {
5136 islight = true;
5137 if (!strcmp(value, "light_fluoro"))
5138 {
5139 originhack[0] = 0;
5140 originhack[1] = 0;
5141 originhack[2] = 0;
5142 overridecolor[0] = 1;
5143 overridecolor[1] = 1;
5144 overridecolor[2] = 1;
5145 }
5146 if (!strcmp(value, "light_fluorospark"))
5147 {
5148 originhack[0] = 0;
5149 originhack[1] = 0;
5150 originhack[2] = 0;
5151 overridecolor[0] = 1;
5152 overridecolor[1] = 1;
5153 overridecolor[2] = 1;
5154 }
5155 if (!strcmp(value, "light_globe"))
5156 {
5157 originhack[0] = 0;
5158 originhack[1] = 0;
5159 originhack[2] = 0;
5160 overridecolor[0] = 1;
5161 overridecolor[1] = 0.8;
5162 overridecolor[2] = 0.4;
5163 }
5164 if (!strcmp(value, "light_flame_large_yellow"))
5165 {
5166 originhack[0] = 0;
5167 originhack[1] = 0;
5168 originhack[2] = 0;
5169 overridecolor[0] = 1;
5170 overridecolor[1] = 0.5;
5171 overridecolor[2] = 0.1;
5172 }
5173 if (!strcmp(value, "light_flame_small_yellow"))
5174 {
5175 originhack[0] = 0;
5176 originhack[1] = 0;
5177 originhack[2] = 0;
5178 overridecolor[0] = 1;
5179 overridecolor[1] = 0.5;
5180 overridecolor[2] = 0.1;
5181 }
5182 if (!strcmp(value, "light_torch_small_white"))
5183 {
5184 originhack[0] = 0;
5185 originhack[1] = 0;
5186 originhack[2] = 0;
5187 overridecolor[0] = 1;
5188 overridecolor[1] = 0.5;
5189 overridecolor[2] = 0.1;
5190 }
5191 if (!strcmp(value, "light_torch_small_walltorch"))
5192 {
5193 originhack[0] = 0;
5194 originhack[1] = 0;
5195 originhack[2] = 0;
5196 overridecolor[0] = 1;
5197 overridecolor[1] = 0.5;
5198 overridecolor[2] = 0.1;
5199 }
5200 }
5201 }
5202 else if (!strcmp("style", key))
5203 style = atoi(value);
5204 else if (!strcmp("skin", key))
5205 skin = (int)atof(value);
5206 else if (!strcmp("pflags", key))
5207 pflags = (int)atof(value);
5208 //else if (!strcmp("effects", key))
5209 // effects = (int)atof(value);
5210 else if (cl.worldmodel->type == mod_brushq3)
5211 {
5212 if (!strcmp("scale", key))
5213 lightscale = atof(value);
5214 if (!strcmp("fade", key))
5215 fadescale = atof(value);
5216 }
5217 }
5218 if (!islight)
5219 continue;
5220 if (lightscale <= 0)
5221 lightscale = 1;
5222 if (fadescale <= 0)
5223 fadescale = 1;
5224 if (color[0] == color[1] && color[0] == color[2])
5225 {
5226 color[0] *= overridecolor[0];
5227 color[1] *= overridecolor[1];
5228 color[2] *= overridecolor[2];
5229 }
5230 radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
5231 color[0] = color[0] * light[0];
5232 color[1] = color[1] * light[1];
5233 color[2] = color[2] * light[2];
5234 switch (type)
5235 {
5236 case LIGHTTYPE_MINUSX:
5237 break;
5238 case LIGHTTYPE_RECIPX:
5239 radius *= 2;
5240 VectorScale(color, (1.0f / 16.0f), color);
5241 break;
5242 case LIGHTTYPE_RECIPXX:
5243 radius *= 2;
5244 VectorScale(color, (1.0f / 16.0f), color);
5245 break;
5246 default:
5247 case LIGHTTYPE_NONE:
5248 break;
5249 case LIGHTTYPE_SUN:
5250 break;
5251 case LIGHTTYPE_MINUSXX:
5252 break;
5253 }
5254 VectorAdd(origin, originhack, origin);
5255 if (radius >= 1)
5256 R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
5257 }
5258 if (entfiledata)
5259 Mem_Free(entfiledata);
5260}
5261
5262
5264{
5265 vec_t dist, push;
5266 vec3_t dest, endpos;
5267 trace_t trace;
5270 if (trace.fraction < 1)
5271 {
5274 if (push > dist)
5275 push = dist;
5276 push = -push;
5277 VectorMA(trace.endpos, push, r_refdef.view.forward, endpos);
5278 VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
5279 }
5280 else
5281 {
5282 VectorClear( endpos );
5283 }
5287}
5288
5299
5304
5323
5325{
5326 if (!cl.worldmodel)
5327 return;
5329}
5330
5336
5342
5344{
5345 vec3_t color;
5346 if (!r_editlights.integer)
5347 {
5348 Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
5349 return;
5350 }
5351 if (Cmd_Argc(cmd) != 1)
5352 {
5353 Con_Print("r_editlights_spawn does not take parameters\n");
5354 return;
5355 }
5356 color[0] = color[1] = color[2] = 1;
5358}
5359
5361{
5363 vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
5364 int style, shadows, flags, normalmode, realtimemode;
5365 char cubemapname[MAX_INPUTLINE];
5366 if (!r_editlights.integer)
5367 {
5368 Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
5369 return;
5370 }
5372 {
5373 Con_Print("No selected light.\n");
5374 return;
5375 }
5382 dp_strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
5383 else
5384 cubemapname[0] = 0;
5385 shadows = r_shadow_selectedlight->shadow;
5387 coronasizescale = r_shadow_selectedlight->coronasizescale;
5388 ambientscale = r_shadow_selectedlight->ambientscale;
5389 diffusescale = r_shadow_selectedlight->diffusescale;
5390 specularscale = r_shadow_selectedlight->specularscale;
5392 normalmode = (flags & LIGHTFLAG_NORMALMODE) != 0;
5393 realtimemode = (flags & LIGHTFLAG_REALTIMEMODE) != 0;
5394 if (!strcmp(Cmd_Argv(cmd, 1), "origin"))
5395 {
5396 if (Cmd_Argc(cmd) != 5)
5397 {
5398 Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(cmd, 1));
5399 return;
5400 }
5401 origin[0] = atof(Cmd_Argv(cmd, 2));
5402 origin[1] = atof(Cmd_Argv(cmd, 3));
5403 origin[2] = atof(Cmd_Argv(cmd, 4));
5404 }
5405 else if (!strcmp(Cmd_Argv(cmd, 1), "originscale"))
5406 {
5407 if (Cmd_Argc(cmd) != 5)
5408 {
5409 Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(cmd, 1));
5410 return;
5411 }
5412 origin[0] *= atof(Cmd_Argv(cmd, 2));
5413 origin[1] *= atof(Cmd_Argv(cmd, 3));
5414 origin[2] *= atof(Cmd_Argv(cmd, 4));
5415 }
5416 else if (!strcmp(Cmd_Argv(cmd, 1), "originx"))
5417 {
5418 if (Cmd_Argc(cmd) != 3)
5419 {
5420 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5421 return;
5422 }
5423 origin[0] = atof(Cmd_Argv(cmd, 2));
5424 }
5425 else if (!strcmp(Cmd_Argv(cmd, 1), "originy"))
5426 {
5427 if (Cmd_Argc(cmd) != 3)
5428 {
5429 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5430 return;
5431 }
5432 origin[1] = atof(Cmd_Argv(cmd, 2));
5433 }
5434 else if (!strcmp(Cmd_Argv(cmd, 1), "originz"))
5435 {
5436 if (Cmd_Argc(cmd) != 3)
5437 {
5438 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5439 return;
5440 }
5441 origin[2] = atof(Cmd_Argv(cmd, 2));
5442 }
5443 else if (!strcmp(Cmd_Argv(cmd, 1), "move"))
5444 {
5445 if (Cmd_Argc(cmd) != 5)
5446 {
5447 Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(cmd, 1));
5448 return;
5449 }
5450 origin[0] += atof(Cmd_Argv(cmd, 2));
5451 origin[1] += atof(Cmd_Argv(cmd, 3));
5452 origin[2] += atof(Cmd_Argv(cmd, 4));
5453 }
5454 else if (!strcmp(Cmd_Argv(cmd, 1), "movex"))
5455 {
5456 if (Cmd_Argc(cmd) != 3)
5457 {
5458 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5459 return;
5460 }
5461 origin[0] += atof(Cmd_Argv(cmd, 2));
5462 }
5463 else if (!strcmp(Cmd_Argv(cmd, 1), "movey"))
5464 {
5465 if (Cmd_Argc(cmd) != 3)
5466 {
5467 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5468 return;
5469 }
5470 origin[1] += atof(Cmd_Argv(cmd, 2));
5471 }
5472 else if (!strcmp(Cmd_Argv(cmd, 1), "movez"))
5473 {
5474 if (Cmd_Argc(cmd) != 3)
5475 {
5476 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5477 return;
5478 }
5479 origin[2] += atof(Cmd_Argv(cmd, 2));
5480 }
5481 else if (!strcmp(Cmd_Argv(cmd, 1), "angles"))
5482 {
5483 if (Cmd_Argc(cmd) != 5)
5484 {
5485 Con_Printf("usage: r_editlights_edit %s x y z\n", Cmd_Argv(cmd, 1));
5486 return;
5487 }
5488 angles[0] = atof(Cmd_Argv(cmd, 2));
5489 angles[1] = atof(Cmd_Argv(cmd, 3));
5490 angles[2] = atof(Cmd_Argv(cmd, 4));
5491 }
5492 else if (!strcmp(Cmd_Argv(cmd, 1), "anglesx"))
5493 {
5494 if (Cmd_Argc(cmd) != 3)
5495 {
5496 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5497 return;
5498 }
5499 angles[0] = atof(Cmd_Argv(cmd, 2));
5500 }
5501 else if (!strcmp(Cmd_Argv(cmd, 1), "anglesy"))
5502 {
5503 if (Cmd_Argc(cmd) != 3)
5504 {
5505 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5506 return;
5507 }
5508 angles[1] = atof(Cmd_Argv(cmd, 2));
5509 }
5510 else if (!strcmp(Cmd_Argv(cmd, 1), "anglesz"))
5511 {
5512 if (Cmd_Argc(cmd) != 3)
5513 {
5514 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5515 return;
5516 }
5517 angles[2] = atof(Cmd_Argv(cmd, 2));
5518 }
5519 else if (!strcmp(Cmd_Argv(cmd, 1), "color"))
5520 {
5521 if (Cmd_Argc(cmd) != 5)
5522 {
5523 Con_Printf("usage: r_editlights_edit %s red green blue\n", Cmd_Argv(cmd, 1));
5524 return;
5525 }
5526 color[0] = atof(Cmd_Argv(cmd, 2));
5527 color[1] = atof(Cmd_Argv(cmd, 3));
5528 color[2] = atof(Cmd_Argv(cmd, 4));
5529 }
5530 else if (!strcmp(Cmd_Argv(cmd, 1), "radius"))
5531 {
5532 if (Cmd_Argc(cmd) != 3)
5533 {
5534 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5535 return;
5536 }
5537 radius = atof(Cmd_Argv(cmd, 2));
5538 }
5539 else if (!strcmp(Cmd_Argv(cmd, 1), "colorscale"))
5540 {
5541 if (Cmd_Argc(cmd) == 3)
5542 {
5543 double scale = atof(Cmd_Argv(cmd, 2));
5544 color[0] *= scale;
5545 color[1] *= scale;
5546 color[2] *= scale;
5547 }
5548 else
5549 {
5550 if (Cmd_Argc(cmd) != 5)
5551 {
5552 Con_Printf("usage: r_editlights_edit %s red green blue (OR grey instead of red green blue)\n", Cmd_Argv(cmd, 1));
5553 return;
5554 }
5555 color[0] *= atof(Cmd_Argv(cmd, 2));
5556 color[1] *= atof(Cmd_Argv(cmd, 3));
5557 color[2] *= atof(Cmd_Argv(cmd, 4));
5558 }
5559 }
5560 else if (!strcmp(Cmd_Argv(cmd, 1), "radiusscale") || !strcmp(Cmd_Argv(cmd, 1), "sizescale"))
5561 {
5562 if (Cmd_Argc(cmd) != 3)
5563 {
5564 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5565 return;
5566 }
5567 radius *= atof(Cmd_Argv(cmd, 2));
5568 }
5569 else if (!strcmp(Cmd_Argv(cmd, 1), "style"))
5570 {
5571 if (Cmd_Argc(cmd) != 3)
5572 {
5573 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5574 return;
5575 }
5576 style = atoi(Cmd_Argv(cmd, 2));
5577 }
5578 else if (!strcmp(Cmd_Argv(cmd, 1), "cubemap"))
5579 {
5580 if (Cmd_Argc(cmd) > 3)
5581 {
5582 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5583 return;
5584 }
5585 if (Cmd_Argc(cmd) == 3)
5586 dp_strlcpy(cubemapname, Cmd_Argv(cmd, 2), sizeof(cubemapname));
5587 else
5588 cubemapname[0] = 0;
5589 }
5590 else if (!strcmp(Cmd_Argv(cmd, 1), "shadows"))
5591 {
5592 if (Cmd_Argc(cmd) != 3)
5593 {
5594 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5595 return;
5596 }
5597 shadows = Cmd_Argv(cmd, 2)[0] == 'y' || Cmd_Argv(cmd, 2)[0] == 'Y' || Cmd_Argv(cmd, 2)[0] == 't' || atoi(Cmd_Argv(cmd, 2));
5598 }
5599 else if (!strcmp(Cmd_Argv(cmd, 1), "corona"))
5600 {
5601 if (Cmd_Argc(cmd) != 3)
5602 {
5603 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5604 return;
5605 }
5606 corona = atof(Cmd_Argv(cmd, 2));
5607 }
5608 else if (!strcmp(Cmd_Argv(cmd, 1), "coronasize"))
5609 {
5610 if (Cmd_Argc(cmd) != 3)
5611 {
5612 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5613 return;
5614 }
5615 coronasizescale = atof(Cmd_Argv(cmd, 2));
5616 }
5617 else if (!strcmp(Cmd_Argv(cmd, 1), "ambient"))
5618 {
5619 if (Cmd_Argc(cmd) != 3)
5620 {
5621 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5622 return;
5623 }
5624 ambientscale = atof(Cmd_Argv(cmd, 2));
5625 }
5626 else if (!strcmp(Cmd_Argv(cmd, 1), "diffuse"))
5627 {
5628 if (Cmd_Argc(cmd) != 3)
5629 {
5630 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5631 return;
5632 }
5633 diffusescale = atof(Cmd_Argv(cmd, 2));
5634 }
5635 else if (!strcmp(Cmd_Argv(cmd, 1), "specular"))
5636 {
5637 if (Cmd_Argc(cmd) != 3)
5638 {
5639 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5640 return;
5641 }
5642 specularscale = atof(Cmd_Argv(cmd, 2));
5643 }
5644 else if (!strcmp(Cmd_Argv(cmd, 1), "normalmode"))
5645 {
5646 if (Cmd_Argc(cmd) != 3)
5647 {
5648 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5649 return;
5650 }
5651 normalmode = Cmd_Argv(cmd, 2)[0] == 'y' || Cmd_Argv(cmd, 2)[0] == 'Y' || Cmd_Argv(cmd, 2)[0] == 't' || atoi(Cmd_Argv(cmd, 2));
5652 }
5653 else if (!strcmp(Cmd_Argv(cmd, 1), "realtimemode"))
5654 {
5655 if (Cmd_Argc(cmd) != 3)
5656 {
5657 Con_Printf("usage: r_editlights_edit %s value\n", Cmd_Argv(cmd, 1));
5658 return;
5659 }
5660 realtimemode = Cmd_Argv(cmd, 2)[0] == 'y' || Cmd_Argv(cmd, 2)[0] == 'Y' || Cmd_Argv(cmd, 2)[0] == 't' || atoi(Cmd_Argv(cmd, 2));
5661 }
5662 else
5663 {
5664 Con_Print("usage: r_editlights_edit [property] [value]\n");
5665 Con_Print("Selected light's properties:\n");
5669 Con_Printf("Radius : %f\n", r_shadow_selectedlight->radius);
5670 Con_Printf("Corona : %f\n", r_shadow_selectedlight->corona);
5671 Con_Printf("Style : %i\n", r_shadow_selectedlight->style);
5672 Con_Printf("Shadows : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
5673 Con_Printf("Cubemap : %s\n", r_shadow_selectedlight->cubemapname);
5674 Con_Printf("CoronaSize : %f\n", r_shadow_selectedlight->coronasizescale);
5677 Con_Printf("Specular : %f\n", r_shadow_selectedlight->specularscale);
5678 Con_Printf("NormalMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");
5679 Con_Printf("RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");
5680 return;
5681 }
5682 flags = (normalmode ? LIGHTFLAG_NORMALMODE : 0) | (realtimemode ? LIGHTFLAG_REALTIMEMODE : 0);
5683 R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
5684}
5685
5687{
5688 size_t lightindex;
5689 dlight_t *light, *oldselected;
5690 size_t range;
5691
5692 if (!r_editlights.integer)
5693 {
5694 Con_Print("Cannot edit lights when not in editing mode. Set r_editlights to 1.\n");
5695 return;
5696 }
5697
5698 oldselected = r_shadow_selectedlight;
5699 // EditLights doesn't seem to have a "remove" command or something so:
5701 for (lightindex = 0;lightindex < range;lightindex++)
5702 {
5704 if (!light)
5705 continue;
5706 R_Shadow_SelectLight(light);
5708 }
5709 // return to old selected (to not mess editing once selection is locked)
5710 R_Shadow_SelectLight(oldselected);
5711}
5712
5714{
5715 int lightnumber, lightcount;
5716 size_t lightindex, range;
5717 dlight_t *light;
5718 char temp[256];
5719 float x, y;
5720
5721 if (!r_editlights.integer)
5722 return;
5723
5724 // update cvars so QC can query them
5726 {
5744 }
5745
5746 // draw properties on screen
5748 return;
5749 x = vid_conwidth.value - 320;
5750 y = 5;
5751 DrawQ_Pic(x-5, y-5, NULL, 250, 243, 0, 0, 0, 0.75, 0);
5752 lightnumber = -1;
5753 lightcount = 0;
5755 for (lightindex = 0;lightindex < range;lightindex++)
5756 {
5758 if (!light)
5759 continue;
5760 if (light == r_shadow_selectedlight)
5761 lightnumber = (int)lightindex;
5762 lightcount++;
5763 }
5764 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;
5765 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;
5766 y += 8;
5768 return;
5769 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;
5770 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;
5771 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;
5772 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;
5773 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;
5774 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;
5775 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;
5776 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;
5777 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;
5778 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;
5779 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;
5780 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;
5781 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;
5782 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;
5783 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;
5784 y += 8;
5785 dpsnprintf(temp, sizeof(temp), "Render stats\n"); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5786 dpsnprintf(temp, sizeof(temp), "Current color: %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.currentcolor[0], r_shadow_selectedlight->rtlight.currentcolor[1], r_shadow_selectedlight->rtlight.currentcolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5787 dpsnprintf(temp, sizeof(temp), "Shadow size : %ix%ix6\n", r_shadow_selectedlight->rtlight.shadowmapatlassidesize, r_shadow_selectedlight->rtlight.shadowmapatlassidesize); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5788 dpsnprintf(temp, sizeof(temp), "World surfs : %i\n", r_shadow_selectedlight->rtlight.cached_numsurfaces); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5789 dpsnprintf(temp, sizeof(temp), "Shadow ents : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numshadowentities, r_shadow_selectedlight->rtlight.cached_numshadowentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5790 dpsnprintf(temp, sizeof(temp), "Lit ents : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numlightentities, r_shadow_selectedlight->rtlight.cached_numlightentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5791 dpsnprintf(temp, sizeof(temp), "BG photons : %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photons); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5792 dpsnprintf(temp, sizeof(temp), "BG radius : %.0f\n", r_shadow_selectedlight->rtlight.bouncegrid_effectiveradius); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5793 dpsnprintf(temp, sizeof(temp), "BG color : %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[0], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[1], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5794 dpsnprintf(temp, sizeof(temp), "BG stats : %i traces %i hits\n", r_shadow_selectedlight->rtlight.bouncegrid_traces, r_shadow_selectedlight->rtlight.bouncegrid_hits); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8;
5795}
5796
5811
5826
5828{
5829 if (!r_editlights.integer)
5830 {
5831 Con_Print("Cannot remove light when not in editing mode. Set r_editlights to 1.\n");
5832 return;
5833 }
5835 {
5836 Con_Print("No selected light.\n");
5837 return;
5838 }
5841}
5842
5844{
5845 Con_Print(
5846"Documentation on r_editlights system:\n"
5847"Settings:\n"
5848"r_editlights : enable/disable editing mode\n"
5849"r_editlights_cursordistance : maximum distance of cursor from eye\n"
5850"r_editlights_cursorpushback : push back cursor this far from surface\n"
5851"r_editlights_cursorpushoff : push cursor off surface this far\n"
5852"r_editlights_cursorgrid : snap cursor to grid of this size\n"
5853"r_editlights_quakelightsizescale : imported quake light entity size scaling\n"
5854"Commands:\n"
5855"r_editlights_help : this help\n"
5856"r_editlights_clear : remove all lights\n"
5857"r_editlights_reload : reload .rtlights, .lights file, or entities\n"
5858"r_editlights_lock : lock selection to current light, if already locked - unlock\n"
5859"r_editlights_save : save to .rtlights file\n"
5860"r_editlights_spawn : create a light with default settings\n"
5861"r_editlights_edit command : edit selected light - more documentation below\n"
5862"r_editlights_remove : remove selected light\n"
5863"r_editlights_toggleshadow : toggles on/off selected light's shadow property\n"
5864"r_editlights_importlightentitiesfrommap : reload light entities\n"
5865"r_editlights_importlightsfile : reload .light file (produced by hlight)\n"
5866"Edit commands:\n"
5867"origin x y z : set light location\n"
5868"originx x: set x component of light location\n"
5869"originy y: set y component of light location\n"
5870"originz z: set z component of light location\n"
5871"move x y z : adjust light location\n"
5872"movex x: adjust x component of light location\n"
5873"movey y: adjust y component of light location\n"
5874"movez z: adjust z component of light location\n"
5875"angles x y z : set light angles\n"
5876"anglesx x: set x component of light angles\n"
5877"anglesy y: set y component of light angles\n"
5878"anglesz z: set z component of light angles\n"
5879"color r g b : set color of light (can be brighter than 1 1 1)\n"
5880"radius radius : set radius (size) of light\n"
5881"colorscale grey : multiply color of light (1 does nothing)\n"
5882"colorscale r g b : multiply color of light (1 1 1 does nothing)\n"
5883"radiusscale scale : multiply radius (size) of light (1 does nothing)\n"
5884"sizescale scale : multiply radius (size) of light (1 does nothing)\n"
5885"originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
5886"style style : set lightstyle of light (flickering patterns, switches, etc)\n"
5887"cubemap basename : set filter cubemap of light\n"
5888"shadows 1/0 : turn on/off shadows\n"
5889"corona n : set corona intensity\n"
5890"coronasize n : set corona size (0-1)\n"
5891"ambient n : set ambient intensity (0-1)\n"
5892"diffuse n : set diffuse intensity (0-1)\n"
5893"specular n : set specular intensity (0-1)\n"
5894"normalmode 1/0 : turn on/off rendering of this light in rtworld 0 mode\n"
5895"realtimemode 1/0 : turn on/off rendering of this light in rtworld 1 mode\n"
5896"<nothing> : print light properties to console\n"
5897 );
5898}
5899
5928
5943
5945{
5946 if (!r_editlights.integer)
5947 {
5948 Con_Print("Cannot lock on light when not in editing mode. Set r_editlights to 1.\n");
5949 return;
5950 }
5952 {
5954 return;
5955 }
5957 {
5958 Con_Print("No selected light to lock on.\n");
5959 return;
5960 }
5962}
5963
5965{
5987 Cmd_AddCommand(CF_CLIENT, "r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
5988 Cmd_AddCommand(CF_CLIENT, "r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
5989 Cmd_AddCommand(CF_CLIENT, "r_editlights_reload", R_Shadow_EditLights_Reload_f, "reloads rtlights file (or imports from .lights file or .ent file or the map itself)");
5990 Cmd_AddCommand(CF_CLIENT, "r_editlights_save", R_Shadow_EditLights_Save_f, "save .rtlights file for current level");
5991 Cmd_AddCommand(CF_CLIENT, "r_editlights_spawn", R_Shadow_EditLights_Spawn_f, "creates a light with default properties (let there be light!)");
5992 Cmd_AddCommand(CF_CLIENT, "r_editlights_edit", R_Shadow_EditLights_Edit_f, "changes a property on the selected light");
5993 Cmd_AddCommand(CF_CLIENT, "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)");
5994 Cmd_AddCommand(CF_CLIENT, "r_editlights_remove", R_Shadow_EditLights_Remove_f, "remove selected light");
5995 Cmd_AddCommand(CF_CLIENT, "r_editlights_toggleshadow", R_Shadow_EditLights_ToggleShadow_f, "toggle on/off the shadow option on the selected light");
5996 Cmd_AddCommand(CF_CLIENT, "r_editlights_togglecorona", R_Shadow_EditLights_ToggleCorona_f, "toggle on/off the corona option on the selected light");
5997 Cmd_AddCommand(CF_CLIENT, "r_editlights_importlightentitiesfrommap", R_Shadow_EditLights_ImportLightEntitiesFromMap_f, "load lights from .ent file or map entities (ignoring .rtlights or .lights file)");
5998 Cmd_AddCommand(CF_CLIENT, "r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)");
5999 Cmd_AddCommand(CF_CLIENT, "r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
6000 Cmd_AddCommand(CF_CLIENT, "r_editlights_pasteinfo", R_Shadow_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)");
6001 Cmd_AddCommand(CF_CLIENT, "r_editlights_lock", R_Shadow_EditLights_Lock_f, "lock selection to current light, if already locked - unlock");
6002}
6003
6004
6005
6006/*
6007=============================================================================
6008
6009LIGHT SAMPLING
6010
6011=============================================================================
6012*/
6013
6014void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity)
6015{
6016 int i, numlights, flag, q;
6017 rtlight_t *light;
6018 dlight_t *dlight;
6019 float relativepoint[3];
6020 float color[3];
6021 float dist;
6022 float dist2;
6023 float intensity;
6024 float sa[3], sx[3], sy[3], sz[3], sd[3];
6025 float lightradius2;
6026
6027 // use first order spherical harmonics to combine directional lights
6028 for (q = 0; q < 3; q++)
6029 sa[q] = sx[q] = sy[q] = sz[q] = sd[q] = 0;
6030
6031 if (flags & LP_LIGHTMAP)
6032 {
6034 {
6035 float tempambient[3];
6036 for (q = 0; q < 3; q++)
6037 tempambient[q] = color[q] = relativepoint[q] = 0;
6038 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint);
6039 // calculate a weighted average light direction as well
6041 for (q = 0; q < 3; q++)
6042 {
6043 sa[q] += (0.5f * color[q] + tempambient[q]) * lightmapintensity;
6044 sx[q] += (relativepoint[0] * color[q]) * lightmapintensity;
6045 sy[q] += (relativepoint[1] * color[q]) * lightmapintensity;
6046 sz[q] += (relativepoint[2] * color[q]) * lightmapintensity;
6047 sd[q] += (intensity * relativepoint[q]) * lightmapintensity;
6048 }
6049 }
6050 else
6051 {
6052 // unlit map - fullbright but scaled by lightmapintensity
6053 for (q = 0; q < 3; q++)
6054 sa[q] += lightmapintensity;
6055 }
6056 }
6057
6058 if (flags & LP_RTWORLD)
6059 {
6062 for (i = 0; i < numlights; i++)
6063 {
6065 if (!dlight)
6066 continue;
6067 light = &dlight->rtlight;
6068 if (!(light->flags & flag))
6069 continue;
6070 // sample
6071 lightradius2 = light->radius * light->radius;
6072 VectorSubtract(light->shadoworigin, p, relativepoint);
6073 dist2 = VectorLength2(relativepoint);
6074 if (dist2 >= lightradius2)
6075 continue;
6076 dist = sqrt(dist2) / light->radius;
6078 if (intensity <= 0.0f)
6079 continue;
6081 continue;
6082 for (q = 0; q < 3; q++)
6083 color[q] = light->currentcolor[q] * intensity;
6085 VectorNormalize(relativepoint);
6086 for (q = 0; q < 3; q++)
6087 {
6088 sa[q] += 0.5f * color[q];
6089 sx[q] += relativepoint[0] * color[q];
6090 sy[q] += relativepoint[1] * color[q];
6091 sz[q] += relativepoint[2] * color[q];
6092 sd[q] += intensity * relativepoint[q];
6093 }
6094 }
6095 // FIXME: sample bouncegrid too!
6096 }
6097
6098 if (flags & LP_DYNLIGHT)
6099 {
6100 // sample dlights
6101 for (i = 0;i < r_refdef.scene.numlights;i++)
6102 {
6103 light = r_refdef.scene.lights[i];
6104 // sample
6105 lightradius2 = light->radius * light->radius;
6106 VectorSubtract(light->shadoworigin, p, relativepoint);
6107 dist2 = VectorLength2(relativepoint);
6108 if (dist2 >= lightradius2)
6109 continue;
6110 dist = sqrt(dist2) / light->radius;
6112 if (intensity <= 0.0f)
6113 continue;
6115 continue;
6116 for (q = 0; q < 3; q++)
6117 color[q] = light->currentcolor[q] * intensity;
6119 VectorNormalize(relativepoint);
6120 for (q = 0; q < 3; q++)
6121 {
6122 sa[q] += 0.5f * color[q];
6123 sx[q] += relativepoint[0] * color[q];
6124 sy[q] += relativepoint[1] * color[q];
6125 sz[q] += relativepoint[2] * color[q];
6126 sd[q] += intensity * relativepoint[q];
6127 }
6128 }
6129 }
6130
6131 // calculate the weighted-average light direction (bentnormal)
6132 for (q = 0; q < 3; q++)
6133 lightdir[q] = sd[q];
6134 VectorNormalize(lightdir);
6135 for (q = 0; q < 3; q++)
6136 {
6137 // extract the diffuse color along the chosen direction and scale it
6138 diffuse[q] = (lightdir[0] * sx[q] + lightdir[1] * sy[q] + lightdir[2] * sz[q]);
6139 // subtract some of diffuse from ambient
6140 ambient[q] = sa[q] + -0.333f * diffuse[q] + ambientintensity;
6141 }
6142}
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
#define SUPERCONTENTS_LIQUIDSMASK
Definition bspfile.h:218
trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities, qbool hitsurfaces)
trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
client_state_t cl
Definition cl_main.c:117
cvar_t vid_conwidth
Definition cl_screen.c:56
#define LIGHTFLAG_NORMALMODE
Definition client.h:34
#define LIGHTFLAG_REALTIMEMODE
Definition client.h:35
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
cmd_state_t * cmd_local
command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses...
Definition cmd.c:25
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
cvar_t collision_extendmovelength
Definition collision.c:14
char com_token[MAX_INPUTLINE]
Definition common.c:39
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
vector size
float flags
vector mins
float skin
vector maxs
vector angles
float entnum
vector origin
string model
const float false
void Cvar_SetValueQuick(cvar_t *var, float value)
Definition cvar.c:473
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
float scale
float style
float pflags
vector color
void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
Definition gl_draw.c:797
#define FONT_DEFAULT
Definition draw.h:128
float DrawQ_String(float x, float y, const char *text, size_t maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor, qbool ignorecolorcodes, const dp_font_t *fnt)
Definition gl_draw.c:1320
#define n(x, y)
qbool FS_WriteFile(const char *filename, const void *data, fs_offset_t len)
Definition fs.c:3592
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
static int(ZEXPORT *qz_inflate)(z_stream *strm
int64_t fs_offset_t
Definition fs.h:37
void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
void GL_BlendEquationSubtract(qbool negated)
void GL_CullFace(int state)
void GL_ColorMask(int r, int g, int b, int a)
unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2) *3]
Definition gl_backend.c:241
void GL_DepthMask(int state)
int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2) *3]
Definition gl_backend.c:240
void GL_DepthFunc(int state)
void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset)
void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane, int offsetx, int offsety)
Definition gl_backend.c:869
void GL_DepthTest(int state)
void GL_DepthRange(float nearfrac, float farfrac)
void R_Mesh_SetRenderTargets(int fbo)
void GL_PolygonOffset(float planeoffset, float depthoffset)
int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
Definition gl_backend.c:960
void R_SetViewport(const r_viewport_t *v)
Definition gl_backend.c:897
void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float nearclip, float farclip, const float *nearplane)
Definition gl_backend.c:587
void R_Mesh_ResetTextureState(void)
void GL_Color(float cr, float cg, float cb, float ca)
void GL_BlendFunc(int blendfunc1, int blendfunc2)
qbool R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
Definition gl_backend.c:430
void GL_Scissor(int x, int y, int width, int height)
void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
void R_Mesh_DestroyFramebufferObject(int fbo)
void R_EntityMatrix(const matrix4x4_t *matrix)
Definition gl_rmain.c:4417
rtexture_t * r_texture_whitecube
Definition gl_rmain.c:277
void R_FrameData_SetMark(void)
set a marker that allows you to discard the following temporary memory allocations
Definition gl_rmain.c:3581
cvar_t r_shadows_castfrombmodels
Definition gl_rmain.c:128
cvar_t r_showlighting
Definition gl_rmain.c:88
cvar_t r_shadows_shadowmapbias
Definition gl_rmain.c:131
void R_GLSL_Restart_f(cmd_state_t *cmd)
Definition gl_rmain.c:1394
void R_SetupShader_Generic_NoTexture(qbool usegamma, qbool notrippy)
Definition gl_rmain.c:1488
qbool R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
Definition gl_rmain.c:3888
void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
Definition gl_rmain.c:7388
void R_FrameData_ReturnToMark(void)
discard recent memory allocations (rewind to marker)
Definition gl_rmain.c:3588
unsigned int r_maxqueries
Definition gl_rmain.c:299
void R_SetupShader_DepthOrShadow(qbool notrippy, qbool depthrgb, qbool skeletal)
Definition gl_rmain.c:1493
cvar_t r_shadows_focus
Definition gl_rmain.c:129
cvar_t r_shadows_darken
Definition gl_rmain.c:124
qbool R_AnimCache_GetEntity(entity_render_t *ent, qbool wantnormals, qbool wanttangents)
get the skeletal data or cached animated mesh data for an entity (optionally with normals and tangent...
Definition gl_rmain.c:3789
void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qbool writedepth, qbool prepass, qbool ui)
Definition gl_rmain.c:10152
cvar_t r_test
Definition gl_rmain.c:235
cvar_t r_shadows_throwdirection
Definition gl_rmain.c:126
void RSurf_DrawBatch(void)
Definition gl_rmain.c:8477
cvar_t r_shadows
Definition gl_rmain.c:123
r_framebufferstate_t r_fb
Definition gl_rmain.c:265
skinframe_t * R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, int comparewidth, int compareheight, int comparecrc, qbool sRGB)
Definition gl_rmain.c:2546
void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
Definition gl_rmain.c:2091
rsurfacestate_t rsurface
Definition gl_rmain.c:6919
mempool_t * r_main_mempool
Definition gl_rmain.c:42
unsigned int r_numqueries
Definition gl_rmain.c:298
void RSurf_SetupDepthAndCulling(bool ui)
Definition gl_rmain.c:8576
cvar_t r_shadows_shadowmapscale
Definition gl_rmain.c:130
rtexture_t * R_GetCubemap(const char *basename)
Definition gl_rmain.c:2982
qbool R_CullBox(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
Definition gl_rmain.c:3470
qbool R_CompileShader_CheckStaticParms(void)
Definition gl_rmain.c:861
void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
Definition gl_rmain.c:6283
cvar_t r_shadows_throwdistance
Definition gl_rmain.c:125
void RSurf_ActiveModelEntity(const entity_render_t *ent, qbool wantnormals, qbool wanttangents, qbool prepass)
Definition gl_rmain.c:6921
void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
Definition gl_rmain.c:2176
cvar_t r_showdisabledepthtest
Definition gl_rmain.c:92
void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qbool notrippy, qbool ui)
Definition gl_rmain.c:1563
qbool R_CullFrustum(const vec3_t mins, const vec3_t maxs)
Definition gl_rmain.c:3464
r_refdef_t r_refdef
Definition gl_rmain.c:57
void * R_FrameData_Store(size_t size, void *data)
allocate some temporary memory and copy this data into it
Definition gl_rmain.c:3573
void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qbool wantnormals, qbool wanttangents)
Definition gl_rmain.c:7146
skinframe_t * R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
Definition gl_rmain.c:2749
unsigned int r_queries[MAX_OCCLUSION_QUERIES]
Definition gl_rmain.c:297
void R_FreeTexturePool(rtexturepool_t **rtexturepool)
rtexture_t * R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype)
int R_TextureHeight(rtexture_t *rt)
void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth, int combine)
rtexture_t * R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qbool filter)
int R_TextureWidth(rtexture_t *rt)
rtexture_t * R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
rtexturepool_t * R_AllocTexturePool(void)
void R_FreeTexture(rtexture_t *rt)
rtexture_t * R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
rtexture_t * R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
GLubyte GLubyte GLubyte z
Definition glquake.h:782
#define GL_ALWAYS
Definition glquake.h:166
unsigned int GLuint
Definition glquake.h:54
#define GL_NONE
Definition glquake.h:127
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
#define CHECKGLERROR
Definition glquake.h:1059
GLint GLenum GLsizei GLsizei GLint border
Definition glquake.h:647
GLubyte GLubyte GLubyte GLubyte w
Definition glquake.h:782
#define GL_UNIFORM_BUFFER
Definition glquake.h:413
int GLint
Definition glquake.h:51
GLsizei samples
Definition glquake.h:623
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition glquake.h:609
GLsizei const GLfloat * value
Definition glquake.h:740
#define GL_READ_BUFFER
Definition glquake.h:195
const GLdouble * v
Definition glquake.h:762
#define GL_SRC_ALPHA
Definition glquake.h:79
GLint GLenum GLint GLint y
Definition glquake.h:651
#define GL_QUERY_RESULT
Definition glquake.h:538
GLint lod
Definition glquake.h:692
#define GL_UNSIGNED_INT
Definition glquake.h:123
#define GL_ZERO
Definition glquake.h:73
GLint GLenum GLint x
Definition glquake.h:651
GLsizeiptr const GLvoid * data
Definition glquake.h:639
#define GL_LEQUAL
Definition glquake.h:162
#define GL_COLOR_BUFFER_BIT
Definition glquake.h:171
#define GL_GREATER
Definition glquake.h:163
#define GL_QUERY_BUFFER
Definition glquake.h:541
#define GL_ONE
Definition glquake.h:74
GLint GLenum GLenum GLvoid * pixels
Definition glquake.h:706
#define GL_DEPTH_COMPONENT
Definition glquake.h:192
#define GL_SAMPLES_PASSED
Definition glquake.h:535
#define GL_STENCIL_BUFFER_BIT
Definition glquake.h:170
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
#define GL_DRAW_BUFFER
Definition glquake.h:194
const GLchar * name
Definition glquake.h:601
#define GL_EQUAL
Definition glquake.h:161
#define GL_DYNAMIC_COPY
Definition glquake.h:308
#define GL_DEPTH_BUFFER_BIT
Definition glquake.h:169
GLuint index
Definition glquake.h:629
GLenum type
Definition glquake.h:656
host_static_t host
Definition host.c:41
cvar_t developer_extra
Definition host.c:49
qbool Image_WriteTGABGRA(const char *filename, int width, int height, const unsigned char *data)
Definition image.c:1436
void Math_RandomSeed_FromInts(randomseed_t *r, unsigned int s0, unsigned int s1, unsigned int s2, unsigned int s3)
Definition mathlib.c:1034
vec3_t vec3_origin
Definition mathlib.c:26
int Math_atov(const char *s, prvm_vec3_t out)
Definition mathlib.c:856
float VectorNormalizeLength(vec3_t v)
returns vector length
Definition mathlib.c:763
void PlaneClassify(mplane_t *p)
Definition mathlib.c:310
#define VectorLerp(v1, lerp, v2, out)
Definition mathlib.h:120
#define max(A, B)
Definition mathlib.h:38
#define VectorNegate(a, b)
Definition mathlib.h:95
#define min(A, B)
Definition mathlib.h:37
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
#define VectorReflect(a, r, b, out)
Definition mathlib.h:121
#define VectorNormalize(v)
Definition mathlib.h:104
#define BoxInsideBox(a, b, c, d)
Definition mathlib.h:123
#define VectorClear(a)
Definition mathlib.h:97
#define bound(min, num, max)
Definition mathlib.h:34
#define VectorLength(a)
Definition mathlib.h:109
#define Vector4Set(vec, r, g, b, a)
Definition mathlib.h:86
#define VectorLength2(a)
Definition mathlib.h:110
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define VectorLehmerRandom(seed, v)
Definition mathlib.h:173
#define VectorDistance2(a, b)
Definition mathlib.h:107
#define PointInfrontOfTriangle(p, a, b, c)
Definition mathlib.h:143
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define CrossProduct(a, b, out)
Definition mathlib.h:103
#define VectorMultiply(a, b, out)
Definition mathlib.h:102
#define VectorCheeseRandom(seed, v)
Definition mathlib.h:172
#define TriangleNormal(a, b, c, n)
Definition mathlib.h:126
#define PlaneDiff(point, plane)
Definition mathlib.h:257
#define VectorDistance(a, b)
Definition mathlib.h:108
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorMAM(scale1, b1, scale2, b2, out)
Definition mathlib.h:116
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
#define VectorCopy4(a, b)
Definition mathlib.h:220
#define TriangleBBoxOverlapsBox(a, b, c, d, e)
Definition mathlib.h:124
#define VectorM(scale1, b1, out)
Definition mathlib.h:115
void Matrix4x4_AdjustOrigin(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:1824
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
Definition matrixlib.c:83
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
void Matrix4x4_FromArrayFloatD3D(matrix4x4_t *out, const float in[16])
Definition matrixlib.c:1282
void Matrix4x4_Transform3x3(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1685
void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale)
Definition matrixlib.c:715
int Matrix4x4_Invert_Full(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:145
void Matrix4x4_CreateScale3(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:695
void Matrix4x4_FromArray12FloatD3D(matrix4x4_t *out, const float in[12])
Definition matrixlib.c:1422
void Matrix4x4_Invert_Simple(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:422
void Matrix4x4_Abs(matrix4x4_t *out)
Definition matrixlib.c:1859
double Matrix4x4_ScaleFromMatrix(const matrix4x4_t *in)
Definition matrixlib.c:1805
const matrix4x4_t identitymatrix
Definition matrixlib.c:9
void Matrix4x4_Scale(matrix4x4_t *out, double rotatescale, double originscale)
Definition matrixlib.c:1837
void Matrix4x4_OriginFromMatrix(const matrix4x4_t *in, float *out)
Definition matrixlib.c:1792
float strlen(string s)
float sqrt(float f)
void cmd(string command,...)
float fabs(float f)
float floor(float f)
void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void(*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
Definition meshqueue.c:33
cvar_t r_trippy
Definition model_brush.c:29
#define MATERIALFLAG_ADD
Definition model_brush.h:81
#define MATERIALFLAG_FULLBRIGHT
Definition model_brush.h:87
#define MATERIALFLAG_ALPHA
Definition model_brush.h:79
#define MATERIALFLAG_REFRACTION
#define MATERIALFLAG_ALPHATEST
#define MATERIALFLAG_BLENDED
#define CHECKPVSBIT(pvs, b)
#define MATERIALFLAG_WATERSHADER
#define MATERIALFLAG_OCCLUDE
#define MATERIALFLAG_NODEPTHTEST
Definition model_brush.h:83
#define MATERIALFLAGMASK_TRANSLUCENT
#define MATERIALFLAG_NOCULLFACE
#define MATERIALFLAG_CUSTOMBLEND
void Mod_AllocLightmap_Reset(mod_alloclightmap_state_t *state)
void Mod_AllocLightmap_Init(mod_alloclightmap_state_t *state, mempool_t *mempool, int width, int height)
void Mod_AllocLightmap_Free(mod_alloclightmap_state_t *state)
void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
qbool Mod_AllocLightmap_Block(mod_alloclightmap_state_t *state, int blockwidth, int blockheight, int *outx, int *outy)
void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i)
@ mod_brushq3
unsigned int palette_bgra_embeddedpic[256]
Definition palette.c:25
#define RENDER_EXTERIORMODEL
Definition protocol.h:359
#define PFLAGS_NOSHADOW
Definition protocol.h:106
#define RENDER_SHADOW
Definition protocol.h:365
#define RENDER_NOSELFSHADOW
Definition protocol.h:367
#define RENDER_LIGHT
Definition protocol.h:366
#define RENDER_NODEPTHTEST
Definition protocol.h:369
#define PFLAGS_CORONA
Definition protocol.h:107
int i
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define MAX_EDICTS
max number of objects in game world at once (32768 protocol limit)
Definition qdefs.h:105
#define MAX_LIGHTSTYLES
max flickering light styles in level (note: affects savegame format)
Definition qdefs.h:108
#define MAX_QPATH
max length of a quake game pathname
Definition qdefs.h:169
#define MAX_OCCLUSION_QUERIES
max number of query objects that can be used in one frame
Definition qdefs.h:124
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
prvm_vec_t prvm_vec3_t[3]
Definition qtypes.h:63
bool qbool
Definition qtypes.h:9
void R_RegisterModule(const char *name, void(*start)(void), void(*shutdown)(void), void(*newmap)(void), void(*devicelost)(void), void(*devicerestored)(void))
Definition r_modules.c:25
@ TRANSPARENTSORT_DISTANCE
Definition r_qshader.h:194
cvar_t r_shadow_glossintensity
Definition r_shadow.c:149
void R_Shadow_RenderMode_Begin(void)
Definition r_shadow.c:1369
cvar_t r_shadow_shadowmapping_filterquality
Definition r_shadow.c:173
static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
Definition r_shadow.c:2920
void R_Shadow_RenderMode_Lighting(qbool transparent, qbool shadowmapping, qbool noselfshadowpass)
Definition r_shadow.c:1597
cvar_t r_shadow_lightradiusscale
Definition r_shadow.c:156
cvar_t r_shadow_shadowmapping_maxsize
Definition r_shadow.c:178
static float spritetexcoord2f[4 *2]
Definition r_shadow.c:4467
cvar_t r_shadow_culllights_trace
Definition r_shadow.c:190
static void R_Shadow_SetShadowmapParametersForLight(qbool noselfshadowpass)
Definition r_shadow.c:1527
static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
Definition r_shadow.c:914
#define BUFFER_OFFSET(i)
unsigned char * r_shadow_buffer_surfacesides
Definition r_shadow.c:100
static void R_Shadow_EditLights_Clear_f(cmd_state_t *cmd)
Definition r_shadow.c:5300
void R_Shadow_EditLights_Reload_f(cmd_state_t *cmd)
Definition r_shadow.c:5305
int * r_shadow_buffer_leaflist
Definition r_shadow.c:95
int r_shadow_viewx
Definition r_shadow.c:127
static void R_Shadow_MakeTextures_MakeCorona(void)
Definition r_shadow.c:1202
cvar_t r_shadow_bumpscale_bumpmap
Definition r_shadow.c:142
cvar_t r_editlights_current_realtimemode
Definition r_shadow.c:257
cvar_t r_shadow_realtime_world_compileportalculling
Definition r_shadow.c:170
static void R_Shadow_SelectLight(dlight_t *light)
Definition r_shadow.c:4700
cvar_t r_shadow_shadowmapping_vsdct
Definition r_shadow.c:176
int r_shadow_buffer_numlighttrispvsbytes
Definition r_shadow.c:104
float r_shadow_modelshadowmap_parameters[4]
Definition r_shadow.c:43
cvar_t r_shadow_culllights_trace_enlarge
Definition r_shadow.c:192
cvar_t r_shadow_usenormalmap
Definition r_shadow.c:146
static void R_Shadow_EditLights_EditAll_f(cmd_state_t *cmd)
Definition r_shadow.c:5686
static void R_Shadow_BounceGrid_BlurPixels_Task(taskqueue_task_t *t)
Definition r_shadow.c:2391
cvar_t r_shadow_lightattenuationdividebias
Definition r_shadow.c:153
static void R_Shadow_BounceGrid_ClearTex_Task(taskqueue_task_t *t)
Definition r_shadow.c:2592
unsigned char * r_shadow_buffer_leafpvs
Definition r_shadow.c:94
void R_Shadow_SetupEntityLight(const entity_render_t *ent)
Definition r_shadow.c:3357
cvar_t r_editlights_current_angles
Definition r_shadow.c:245
cvar_t r_shadow_culllights_trace_expand
Definition r_shadow.c:193
void R_Shadow_PrepareShadowSides(int numtris)
Definition r_shadow.c:848
int bboxedges[12][2]
Definition r_shadow.c:2881
static void R_Shadow_BounceGrid_UpdateSpacing(void)
Definition r_shadow.c:1751
static void R_Shadow_EditLights_Lock_f(cmd_state_t *cmd)
Definition r_shadow.c:5944
int r_shadow_shadowmappcf
Definition r_shadow.c:60
cvar_t r_shadow_bouncegrid_static
Definition r_shadow.c:223
int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
Definition r_shadow.c:863
cvar_t r_shadow_bouncegrid_static_maxbounce
Definition r_shadow.c:227
void R_Shadow_EditLights_DrawSelectedLightProperties(void)
Definition r_shadow.c:5713
cvar_t r_shadow_bouncegrid_static_lightradiusscale
Definition r_shadow.c:226
int maxshadowmark
Definition r_shadow.c:76
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)
Definition r_shadow.c:1058
cvar_t r_shadow_shadowmapping_nearclip
Definition r_shadow.c:184
void R_Shadow_DrawLightSprites(void)
Definition r_shadow.c:4762
qbool R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
Definition r_shadow.c:2900
cvar_t r_shadow_usebihculling
Definition r_shadow.c:145
cvar_t r_editlights_current_color
Definition r_shadow.c:246
rtexture_t * r_shadow_prepassgeometrynormalmaptexture
Definition r_shadow.c:120
rtexture_t * r_shadow_prepasslightingdiffusetexture
Definition r_shadow.c:121
int r_shadow_lightscissor[4]
Definition r_shadow.c:63
vec3_t r_editlights_cursorlocation
Definition r_shadow.c:276
skinframe_t * r_editlights_sprnoshadowlight
Definition r_shadow.c:293
void R_Shadow_ClearStencil(void)
Definition r_shadow.c:1430
GLuint r_shadow_prepasslightingdiffusefbo
Definition r_shadow.c:116
static void R_Shadow_FreeDeferred(void)
Definition r_shadow.c:3930
static void R_Shadow_BounceGrid_EnqueueSlices_Task(taskqueue_task_t *t)
Definition r_shadow.c:2341
void R_Shadow_DrawShadowMaps(void)
Definition r_shadow.c:4204
cvar_t r_shadow_realtime_dlight
Definition r_shadow.c:159
void R_Shadow_UncompileWorldLights(void)
Definition r_shadow.c:3133
static void R_Shadow_BounceGrid_Slice(int zi)
Definition r_shadow.c:2170
int r_shadow_shadowmapmaxsize
Definition r_shadow.c:55
void R_Shadow_LoadLightsFile(void)
Definition r_shadow.c:4987
cvar_t r_shadow_bouncegrid_dynamic_hitmodels
Definition r_shadow.c:204
#define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias)
Definition r_shadow.c:964
static void R_Shadow_BounceGrid_FreeHighPixels(void)
Definition r_shadow.c:490
cvar_t r_shadow_bouncegrid_includedirectlighting
Definition r_shadow.c:215
cvar_t r_shadow_shadowmapping_bordersize
Definition r_shadow.c:183
int r_shadow_scenenumlights
Definition r_shadow.c:35
unsigned char * r_shadow_buffer_surfacepvs
Definition r_shadow.c:98
cvar_t r_editlights_current_style
Definition r_shadow.c:250
rtexture_t * r_shadow_prepasslightingspeculartexture
Definition r_shadow.c:122
int maxshadowsides
Definition r_shadow.c:82
char r_shadow_mapname[MAX_QPATH]
Definition r_shadow.c:133
void R_Shadow_PrepareShadowMark(int numtris)
Definition r_shadow.c:824
unsigned char * r_shadow_buffer_visitingleafpvs
Definition r_shadow.c:93
qbool r_shadow_shadowmapshadowsampler
Definition r_shadow.c:59
static void R_Shadow_EditLights_Save_f(cmd_state_t *cmd)
Definition r_shadow.c:5324
cvar_t r_shadow_debuglight
Definition r_shadow.c:143
cvar_t r_shadow_shadowmapping_minsize
Definition r_shadow.c:177
int r_shadow_buffer_numshadowtrispvsbytes
Definition r_shadow.c:102
int * vertexupdate
Definition r_shadow.c:88
#define ATTEN2DSIZE
Definition r_shadow.c:265
cvar_t r_editlights_cursorpushoff
Definition r_shadow.c:240
cvar_t r_shadow_culllights_trace_samples
Definition r_shadow.c:195
static void R_Shadow_EditLights_Remove_f(cmd_state_t *cmd)
Definition r_shadow.c:5827
cvar_t r_shadow_realtime_world_shadows
Definition r_shadow.c:166
cvar_t r_shadow_shadowmapping_depthbits
Definition r_shadow.c:175
qbool r_shadow_shadowmapvsdct
Definition r_shadow.c:57
cvar_t r_shadow_bouncegrid_dynamic_dlightparticlemultiplier
Definition r_shadow.c:203
static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
Definition r_shadow.c:4709
cvar_t r_shadow_bouncegrid_dynamic_maxbounce
Definition r_shadow.c:206
static void R_Shadow_FreeShadowMaps(void)
Definition r_shadow.c:390
int r_shadow_cullface_front
Definition r_shadow.c:48
cvar_t r_editlights_current_normalmode
Definition r_shadow.c:256
cvar_t r_shadow_sortsurfaces
Definition r_shadow.c:188
int r_shadow_shadowmode_shadowmapping
Definition r_shadow.c:50
skinframe_t * r_editlights_sprlight
Definition r_shadow.c:292
static void R_Shadow_EditLights_ToggleCorona_f(cmd_state_t *cmd)
Definition r_shadow.c:5812
qbool r_shadow_usingdeferredprepass
Definition r_shadow.c:64
cvar_t r_shadow_realtime_world
Definition r_shadow.c:163
static void R_Shadow_DrawEntityLight(entity_render_t *ent)
Definition r_shadow.c:3384
cvar_t r_shadow_bouncegrid_static_quality
Definition r_shadow.c:229
rtexture_t * r_shadow_viewdepthtexture
Definition r_shadow.c:125
static float R_Shadow_BounceGrid_RefractiveIndexAtPoint(vec3_t point)
Definition r_shadow.c:1902
int maxshadowtriangles
Definition r_shadow.c:70
int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
Definition r_shadow.c:4777
cvar_t r_shadow_bouncegrid_static_directionalshading
Definition r_shadow.c:225
cvar_t r_shadow_realtime_dlight_svbspculling
Definition r_shadow.c:161
cvar_t r_shadow_shadowmapping
Definition r_shadow.c:172
cvar_t r_shadow_scissor
Definition r_shadow.c:171
static void R_Shadow_EditLights_CopyInfo_f(cmd_state_t *cmd)
Definition r_shadow.c:5900
static void R_Shadow_EditLights_Edit_f(cmd_state_t *cmd)
Definition r_shadow.c:5360
int r_shadow_viewfbo
Definition r_shadow.c:124
cvar_t r_shadow_bouncegrid_particleintensity
Definition r_shadow.c:220
mod_alloclightmap_state_t r_shadow_shadowmapatlas_state
Definition r_shadow.c:66
cvar_t r_shadow_shadowmapping_precision
Definition r_shadow.c:180
static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(cmd_state_t *cmd)
Definition r_shadow.c:5331
static void R_Shadow_MakeTextures(void)
Definition r_shadow.c:1232
int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
Definition r_shadow.c:966
cvar_t r_shadow_bouncegrid_lightpathsize
Definition r_shadow.c:217
cvar_t r_shadow_projectdistance
Definition r_shadow.c:157
int r_shadow_shadowmapfilterquality
Definition r_shadow.c:53
cvar_t r_coronas
Definition r_shadow.c:233
cvar_t r_shadow_shadowmapping_useshadowsampler
Definition r_shadow.c:174
#define ATTENTABLESIZE
Definition r_shadow.c:262
static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
Definition r_shadow.c:754
static entity_render_t * r_shadow_modelshadows[MAX_MODELSHADOWS]
Definition r_shadow.c:4240
int r_shadow_shadowmapside
Definition r_shadow.c:39
r_shadow_rendermode_t r_shadow_rendermode
Definition r_shadow.c:32
rtexture_t * r_shadow_attenuationgradienttexture
Definition r_shadow.c:108
static void R_Shadow_EditLights_Init(void)
Definition r_shadow.c:5964
dlight_t * r_shadow_selectedlight
Definition r_shadow.c:274
int numshadowsides
Definition r_shadow.c:83
static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
Definition r_shadow.c:776
static void R_Shadow_SetCursorLocationForView(void)
Definition r_shadow.c:5263
cvar_t r_shadow_realtime_world_importlightentitiesfrommap
Definition r_shadow.c:164
cvar_t r_editlights_cursordistance
Definition r_shadow.c:238
static void R_Shadow_MakeVSDCT(void)
Definition r_shadow.c:1436
qbool r_shadow_shadowmapsampler
Definition r_shadow.c:58
int maxshadowvertices
Definition r_shadow.c:73
cvar_t r_editlights_quakelightsizescale
Definition r_shadow.c:242
int r_shadow_shadowmapdepthbits
Definition r_shadow.c:54
void R_Shadow_RenderMode_DrawDeferredLight(qbool shadowmapping)
Definition r_shadow.c:1642
void R_Shadow_PrepareLights(void)
Definition r_shadow.c:4031
int maxvertexupdate
Definition r_shadow.c:87
qbool R_Shadow_ShadowMappingEnabled(void)
Definition r_shadow.c:378
cvar_t r_editlights_current_cubemap
Definition r_shadow.c:252
cvar_t r_shadow_bouncegrid_intensity
Definition r_shadow.c:216
static void R_Shadow_BounceGrid_TracePhotons_ShotTask(taskqueue_task_t *t)
Definition r_shadow.c:2727
unsigned char * r_shadow_buffer_lighttrispvs
Definition r_shadow.c:105
static const unsigned short bboxelements[36]
Definition r_shadow.c:1620
int * shadowmark
Definition r_shadow.c:78
GLuint r_shadow_prepasslightingdiffusespecularfbo
Definition r_shadow.c:115
cvar_t r_editlights_current_coronasize
Definition r_shadow.c:249
float r_shadow_lightshadowmap_parameters[4]
Definition r_shadow.c:41
static void R_Shadow_BounceGrid_TracePhotons_Shot(r_shadow_bouncegrid_photon_t *p, int remainingbounces, vec3_t shotstart, vec3_t shotend, vec3_t shotcolor, float bounceminimumintensity2, float previousrefractiveindex)
Definition r_shadow.c:2598
cvar_t r_shadow_bouncegrid_dynamic_bounceminimumintensity
Definition r_shadow.c:200
int * r_shadow_buffer_surfacelist
Definition r_shadow.c:99
void R_Shadow_PrepareModelShadows(void)
Definition r_shadow.c:4242
cvar_t r_editlights_current_origin
Definition r_shadow.c:244
cvar_t r_shadow_bouncegrid_rng_seed
Definition r_shadow.c:221
skinframe_t * r_editlights_sprcursor
Definition r_shadow.c:291
cvar_t r_editlights
Definition r_shadow.c:237
static qbool R_Shadow_PrepareLights_AddSceneLight(rtlight_t *rtlight)
Definition r_shadow.c:4016
cvar_t r_shadow_bouncegrid_static_bounceminimumintensity
Definition r_shadow.c:224
qbool r_shadow_usingshadowmap2d
Definition r_shadow.c:37
cvar_t r_shadow_culllights_trace_eyejitter
Definition r_shadow.c:191
cvar_t r_shadow_bouncegrid_dynamic_lightradiusscale
Definition r_shadow.c:205
static void R_Shadow_EditLights_ToggleShadow_f(cmd_state_t *cmd)
Definition r_shadow.c:5797
cvar_t r_shadow_culllights_trace_pad
Definition r_shadow.c:194
cvar_t r_shadow_bouncegrid_dynamic_updateinterval
Definition r_shadow.c:210
rtexture_t * r_shadow_prepassgeometrydepthbuffer
Definition r_shadow.c:119
cvar_t r_shadow_bouncegrid_static_spacing
Definition r_shadow.c:230
r_shadow_shadowmode_t
Definition r_shadow.c:26
@ R_SHADOW_SHADOWMODE_DISABLED
Definition r_shadow.c:27
@ R_SHADOW_SHADOWMODE_SHADOWMAP2D
Definition r_shadow.c:28
float * shadowvertex3f
Definition r_shadow.c:74
void R_RTLight_Uncompile(rtlight_t *rtlight)
Definition r_shadow.c:3109
static void R_Shadow_MakeShadowMap(int texturesize)
Definition r_shadow.c:1456
int r_shadow_shadowmaptexturesize
Definition r_shadow.c:56
cvar_t r_shadow_glossexact
Definition r_shadow.c:152
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)
Definition r_shadow.c:2980
int numshadowmark
Definition r_shadow.c:77
static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3])
Definition r_shadow.c:2928
#define EDLIGHTSPRSIZE
Definition r_shadow.c:290
static void R_Shadow_DrawLightShadowMaps(rtlight_t *rtlight)
Definition r_shadow.c:3700
r_shadow_shadowmode_t r_shadow_shadowmode
Definition r_shadow.c:52
cvar_t r_editlights_current_corona
Definition r_shadow.c:248
static void r_shadow_shutdown(void)
Definition r_shadow.c:503
float r_shadow_lightshadowmap_texturescale[4]
Definition r_shadow.c:40
cvar_t r_shadow_lightintensityscale
Definition r_shadow.c:155
void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
Definition r_shadow.c:2936
rtexture_t * r_shadow_viewcolortexture
Definition r_shadow.c:126
cvar_t r_editlights_cursorpushback
Definition r_shadow.c:239
cvar_t r_editlights_cursorgrid
Definition r_shadow.c:241
cvar_t r_shadow_bouncegrid_subsamples
Definition r_shadow.c:231
cvar_t r_shadow_bouncegrid_particlebounceintensity
Definition r_shadow.c:219
rtlight_t ** r_shadow_scenelightlist
Definition r_shadow.c:36
matrix4x4_t matrix_attenuationz
Definition r_shadow.c:744
cvar_t r_shadow_realtime_world_compile
Definition r_shadow.c:167
static const float bboxpoints[8][3]
Definition r_shadow.c:1630
void R_Shadow_RenderMode_VisibleLighting(qbool transparent)
Definition r_shadow.c:2860
static void R_Shadow_DrawModelShadowMaps(void)
Definition r_shadow.c:4311
r_shadow_rendermode_t r_shadow_lightingrendermode
Definition r_shadow.c:33
matrix4x4_t matrix_attenuationxyz
Definition r_shadow.c:734
int r_shadow_viewy
Definition r_shadow.c:128
skinframe_t * r_editlights_sprselection
Definition r_shadow.c:296
static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
Definition r_shadow.c:4718
static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
Definition r_shadow.c:3339
int r_shadow_buffer_numleafpvsbytes
Definition r_shadow.c:92
GLuint r_shadow_prepassgeometryfbo
Definition r_shadow.c:114
cvar_t r_editlights_current_ambient
Definition r_shadow.c:253
cvar_t r_shadow_gloss
Definition r_shadow.c:147
static void R_Shadow_BounceGrid_EnqueuePhotons_Task(taskqueue_task_t *t)
Definition r_shadow.c:2734
static void R_Shadow_EditLights_PasteInfo_f(cmd_state_t *cmd)
Definition r_shadow.c:5929
static int r_shadow_nummodelshadows
Definition r_shadow.c:4239
cvar_t r_shadow_realtime_world_compilesvbsp
Definition r_shadow.c:169
static void R_Shadow_RenderMode_ShadowMap(int side, int size, int x, int y)
Definition r_shadow.c:1549
cvar_t r_shadow_bouncegrid_dynamic_y
Definition r_shadow.c:212
static float r_shadow_attendividebias
Definition r_shadow.c:268
int r_shadow_prepass_width
Definition r_shadow.c:117
cvar_t r_shadow_bouncegrid_rng_type
Definition r_shadow.c:222
rtlight_t * r_shadow_compilingrtlight
Definition r_shadow.c:272
qbool r_shadow_usingshadowmaportho
Definition r_shadow.c:38
unsigned char * shadowsides
Definition r_shadow.c:84
r_shadow_rendermode_t
Definition r_shadow.c:10
@ R_SHADOW_RENDERMODE_VISIBLEVOLUMES
Definition r_shadow.c:19
@ R_SHADOW_RENDERMODE_NONE
Definition r_shadow.c:11
@ R_SHADOW_RENDERMODE_ZPASS_STENCIL
Definition r_shadow.c:12
@ R_SHADOW_RENDERMODE_SHADOWMAP2D
Definition r_shadow.c:21
@ R_SHADOW_RENDERMODE_ZFAIL_STENCIL
Definition r_shadow.c:15
@ R_SHADOW_RENDERMODE_VISIBLELIGHTING
Definition r_shadow.c:20
@ R_SHADOW_RENDERMODE_LIGHT_GLSL
Definition r_shadow.c:18
@ R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL
Definition r_shadow.c:16
@ R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL
Definition r_shadow.c:13
@ R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE
Definition r_shadow.c:17
@ R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE
Definition r_shadow.c:14
#define MAX_SCENELIGHTS
Definition r_shadow.c:4015
static dlight_t * R_Shadow_NewWorldLight(void)
Definition r_shadow.c:4634
cvar_t r_shadow_frontsidecasting
Definition r_shadow.c:158
static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
Definition r_shadow.c:2418
skinframe_t * r_editlights_sprcubemaplight
Definition r_shadow.c:294
void R_Shadow_ClearWorldLights(void)
Definition r_shadow.c:4686
rtexturepool_t * r_shadow_texturepool
Definition r_shadow.c:107
cvar_t r_shadow_culllights_pvs
Definition r_shadow.c:189
void R_Shadow_UpdateBounceGridTexture(void)
Definition r_shadow.c:2755
void R_Shadow_RenderMode_Reset(void)
Definition r_shadow.c:1409
int shadowmarkcount
Definition r_shadow.c:80
cvar_t r_shadow_realtime_world_compileshadow
Definition r_shadow.c:168
int * shadowsideslist
Definition r_shadow.c:85
static void R_Shadow_BounceGrid_AssignPhotons_Task(taskqueue_task_t *t)
Definition r_shadow.c:1922
cvar_t r_shadow_bouncegrid_blur
Definition r_shadow.c:199
static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
Definition r_shadow.c:1224
rtexture_t * r_shadow_shadowmapvsdcttexture
Definition r_shadow.c:112
cvar_t r_shadow_bouncegrid_dynamic_maxphotons
Definition r_shadow.c:207
int r_shadow_scenemaxlights
Definition r_shadow.c:34
cvar_t r_shadow_bouncegrid_normalizevectors
Definition r_shadow.c:218
cvar_t r_shadow_deferred
Definition r_shadow.c:144
cvar_t gl_lightmaps
Definition gl_rmain.c:233
cvar_t r_shadow_culllights_trace_delay
Definition r_shadow.c:197
rtexture_t * r_shadow_shadowmap2ddepthtexture
Definition r_shadow.c:111
unsigned char * r_shadow_buffer_shadowtrispvs
Definition r_shadow.c:103
static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qbool usequery)
Definition r_shadow.c:4420
int r_shadow_shadowmapatlas_modelshadows_size
Definition r_shadow.c:69
static float r_shadow_attenlinearscale
Definition r_shadow.c:269
cvar_t r_shadow_bouncegrid
Definition r_shadow.c:198
matrix4x4_t r_shadow_shadowmapmatrix
Definition r_shadow.c:62
void R_Shadow_DrawCoronas(void)
Definition r_shadow.c:4528
void R_Shadow_Init(void)
Definition r_shadow.c:601
int r_shadow_prepass_height
Definition r_shadow.c:118
GLuint r_shadow_fbo2d
Definition r_shadow.c:49
int r_shadow_shadowmapatlas_modelshadows_y
Definition r_shadow.c:68
cvar_t r_shadow_realtime_dlight_portalculling
Definition r_shadow.c:162
static memexpandablearray_t r_shadow_worldlightsarray
Definition r_shadow.c:273
static void r_shadow_start(void)
Definition r_shadow.c:416
static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t *settings)
Definition r_shadow.c:1708
static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
Definition r_shadow.c:983
static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
Definition r_shadow.c:3316
cvar_t r_shadow_gloss2intensity
Definition r_shadow.c:148
void R_Shadow_SaveWorldLights(void)
Definition r_shadow.c:4932
static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
Definition r_shadow.c:3147
int r_shadow_buffer_numsurfacepvsbytes
Definition r_shadow.c:97
void R_Shadow_LoadWorldLights(void)
Definition r_shadow.c:4829
int * shadowmarklist
Definition r_shadow.c:79
cvar_t r_shadow_lightattenuationlinearscale
Definition r_shadow.c:154
cvar_t r_shadow_bouncegrid_dynamic_z
Definition r_shadow.c:213
rtexture_t * r_shadow_shadowmap2ddepthbuffer
Definition r_shadow.c:110
cvar_t r_shadow_realtime_dlight_shadows
Definition r_shadow.c:160
cvar_t r_shadow_bouncegrid_dynamic_spacing
Definition r_shadow.c:209
cvar_t r_coronas_occlusionquery
Definition r_shadow.c:235
cvar_t r_shadow_bouncegrid_dynamic_culllightpaths
Definition r_shadow.c:201
cvar_t r_editlights_current_diffuse
Definition r_shadow.c:254
int con_vislines
Definition console.c:95
void R_Shadow_DrawLights(void)
Definition r_shadow.c:4226
cvar_t r_shadow_glossexponent
Definition r_shadow.c:150
static void R_Shadow_DrawLight(rtlight_t *rtlight)
Definition r_shadow.c:3838
cvar_t r_shadow_shadowmapping_bias
Definition r_shadow.c:185
dlight_t r_shadow_bufferlight
Definition r_shadow.c:275
qbool r_shadow_shadowmapdepthtexture
Definition r_shadow.c:65
#define ATTEN3DSIZE
Definition r_shadow.c:266
void R_Shadow_ClearShadowMapTexture(void)
Definition r_shadow.c:1480
#define MAX_MODELSHADOWS
Definition r_shadow.c:4238
cvar_t r_shadow_bouncegrid_floatcolors
Definition r_shadow.c:214
int r_shadow_cullface_back
Definition r_shadow.c:48
cvar_t r_shadow_gloss2exponent
Definition r_shadow.c:151
static qbool R_Shadow_BounceGrid_CheckEnable(int flag)
Definition r_shadow.c:1674
static void R_Shadow_EditLights_ImportLightsFile_f(cmd_state_t *cmd)
Definition r_shadow.c:5337
cvar_t r_shadow_bouncegrid_dynamic_quality
Definition r_shadow.c:208
lighttype_t
Definition r_shadow.c:5036
@ LIGHTTYPE_MINUSX
Definition r_shadow.c:5036
@ LIGHTTYPE_RECIPXX
Definition r_shadow.c:5036
@ LIGHTTYPE_MINUSXX
Definition r_shadow.c:5036
@ LIGHTTYPE_NONE
Definition r_shadow.c:5036
@ LIGHTTYPE_SUN
Definition r_shadow.c:5036
@ LIGHTTYPE_RECIPX
Definition r_shadow.c:5036
static void R_Shadow_BounceGrid_BlurPixelsInDirection(const float *inpixels, float *outpixels, int off)
Definition r_shadow.c:2359
static void R_Shadow_SetShadowMode(void)
Definition r_shadow.c:301
void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
Definition r_shadow.c:1404
static float r_shadow_attentable[ATTENTABLESIZE+1]
Definition r_shadow.c:270
static void r_shadow_newmap(void)
Definition r_shadow.c:585
cvar_t r_editlights_current_radius
Definition r_shadow.c:247
void R_Shadow_RenderMode_End(void)
Definition r_shadow.c:2872
cvar_t r_shadow_culllights_trace_tempsamples
Definition r_shadow.c:196
void R_Shadow_DrawPrepass(void)
Definition r_shadow.c:3958
cvar_t r_shadow_bouncegrid_threaded
Definition r_shadow.c:232
static void R_Shadow_BounceGrid_Slice_Task(taskqueue_task_t *t)
Definition r_shadow.c:2335
cvar_t r_shadow_bouncegrid_dynamic_x
Definition r_shadow.c:211
void R_Shadow_UpdateWorldLightSelection(void)
Definition r_shadow.c:5289
int r_shadow_shadowmode_deferred
Definition r_shadow.c:51
int r_shadow_shadowmapborder
Definition r_shadow.c:61
unsigned int r_shadow_occlusion_buf
Definition r_shadow.c:136
skinframe_t * r_editlights_sprcubemapnoshadowlight
Definition r_shadow.c:295
cvar_t r_shadow_bouncegrid_dynamic_directionalshading
Definition r_shadow.c:202
void R_RTLight_Compile(rtlight_t *rtlight)
Definition r_shadow.c:3023
#define ATTEN1DSIZE
Definition r_shadow.c:264
cvar_t r_editlights_current_specular
Definition r_shadow.c:255
cvar_t r_shadow_realtime_world_lightmaps
Definition r_shadow.c:165
int r_shadow_viewwidth
Definition r_shadow.c:129
int * shadowelements
Definition r_shadow.c:71
skinframe_t * r_shadow_lightcorona
Definition r_shadow.c:109
cvar_t r_shadow_bumpscale_basetexture
Definition r_shadow.c:141
rtexturepool_t * r_shadow_filters_texturepool
Definition r_shadow.c:139
cvar_t r_shadow_shadowmapping_polygonoffset
Definition r_shadow.c:187
int r_shadow_viewheight
Definition r_shadow.c:130
void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
Definition r_shadow.c:5038
static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
Definition r_shadow.c:3367
cvar_t r_shadow_bouncegrid_static_maxphotons
Definition r_shadow.c:228
int r_shadow_shadowmapatlas_modelshadows_x
Definition r_shadow.c:67
static void R_Shadow_SelectLightInView(void)
Definition r_shadow.c:4797
cvar_t r_editlights_current_shadows
Definition r_shadow.c:251
int vertexupdatenum
Definition r_shadow.c:90
static void R_Shadow_PrepareLight(rtlight_t *rtlight)
Definition r_shadow.c:3397
cvar_t r_shadow_shadowmapping_texturesize
Definition r_shadow.c:179
r_shadow_bouncegrid_state_t r_shadow_bouncegrid_state
Definition r_shadow.c:259
static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
Definition r_shadow.c:4469
static void R_Shadow_EditLights_Spawn_f(cmd_state_t *cmd)
Definition r_shadow.c:5343
static 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)
Definition r_shadow.c:4639
void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity)
Definition r_shadow.c:6014
static void R_Shadow_FreeWorldLight(dlight_t *light)
Definition r_shadow.c:4678
cvar_t r_coronas_occlusionsizescale
Definition r_shadow.c:234
cvar_t gl_flashblend
Definition r_shadow.c:236
cvar_t r_shadow_shadowmapping_polygonfactor
Definition r_shadow.c:186
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)
Definition r_shadow.c:1162
qbool r_editlights_lockcursor
Definition r_shadow.c:277
cvar_t r_editlights_drawproperties
Definition r_shadow.c:243
static void R_Shadow_EditLights_Help_f(cmd_state_t *cmd)
Definition r_shadow.c:5843
int * vertexremap
Definition r_shadow.c:89
float r_shadow_modelshadowmap_texturescale[4]
Definition r_shadow.c:42
#define PHOTON_MAX_PATHS
Definition r_shadow.h:68
#define LP_DYNLIGHT
Definition r_shadow.h:194
#define LP_LIGHTMAP
Definition r_shadow.h:192
#define LP_RTWORLD
Definition r_shadow.h:193
int r_timereport_active
Definition r_stats.c:189
void R_TimeReport(const char *desc)
Definition r_stats.c:193
@ r_stat_bouncegrid_particles
Definition r_stats.h:34
@ r_stat_bouncegrid_lights
Definition r_stats.h:33
@ r_stat_lights_clears
Definition r_stats.h:28
@ r_stat_lights
Definition r_stats.h:27
@ r_stat_lights_scissored
Definition r_stats.h:29
@ r_stat_lights_shadowtriangles
Definition r_stats.h:31
#define TEXF_ALPHA
Definition r_textures.h:9
#define TEXF_FORCELINEAR
Definition r_textures.h:19
#define TEXF_FORCENEAREST
Definition r_textures.h:17
@ TEXTYPE_SHADOWMAP16_RAW
Definition r_textures.h:98
@ TEXTYPE_COLORBUFFER
Definition r_textures.h:84
@ TEXTYPE_SHADOWMAP16_COMP
Definition r_textures.h:96
@ TEXTYPE_COLORBUFFER32F
Definition r_textures.h:88
@ TEXTYPE_DEPTHBUFFER24
Definition r_textures.h:92
@ TEXTYPE_DEPTHBUFFER16
Definition r_textures.h:90
@ TEXTYPE_BGRA
Definition r_textures.h:53
@ TEXTYPE_RGBA
Definition r_textures.h:51
@ TEXTYPE_SHADOWMAP24_RAW
Definition r_textures.h:102
@ TEXTYPE_SHADOWMAP24_COMP
Definition r_textures.h:100
@ TEXTYPE_COLORBUFFER16F
Definition r_textures.h:86
#define TEXF_CLAMP
Definition r_textures.h:15
#define TEXF_RENDERTARGET
Definition r_textures.h:37
#define BATCHNEED_NOGAPS
Definition render.h:793
#define BATCHNEED_ARRAY_VERTEX
Definition render.h:785
@ RSURFPASS_RTLIGHT
Definition render.h:806
vec4 refractcolor
float Fresnel
precision highp float
Definition shader_glsl.h:53
float f
vec3 normal
ret a
float intensity
Definition snd_mix.c:314
struct model_s * worldmodel
Definition client.h:934
char worldname[MAX_QPATH]
Definition client.h:899
csqc_vidvars_t csqc_vidvars
Definition client.h:834
char worldnamenoextension[MAX_QPATH]
Definition client.h:900
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
qbool drawworld
Definition client.h:706
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
const char * string
Definition cvar.h:71
vec3_t angles
Definition client.h:246
int flags
Definition client.h:295
vec_t coronasizescale
Definition client.h:283
rtlight_t rtlight
Definition client.h:301
vec3_t origin
Definition client.h:242
int style
Definition client.h:274
vec_t corona
Definition client.h:280
int shadow
Definition client.h:277
vec3_t color
Definition client.h:252
vec_t ambientscale
Definition client.h:286
char cubemapname[64]
Definition client.h:255
vec_t diffusescale
Definition client.h:289
vec_t specularscale
Definition client.h:292
vec_t radius
Definition client.h:261
int selected
Definition client.h:258
matrix4x4_t inversematrix
Definition client.h:334
matrix4x4_t matrix
Definition client.h:332
vec3_t mins
Definition client.h:371
model_t * model
Definition client.h:343
vec3_t maxs
Definition client.h:371
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
vec_t m[4][4]
Definition matrixlib.h:11
int(* BoxTouchingVisibleLeafs)(struct model_s *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
void(* LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
int(* BoxTouchingLeafPVS)(struct model_s *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
model_brush_t brush
surfmesh_t surfmesh
qbool lit
int * modelsurfaces_sorted
surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index)
int submodelsurfaces_end
msurface_t * data_surfaces
int submodelsurfaces_start
void(* DrawPrepass)(struct entity_render_s *ent)
vec3_t normalmaxs
void(* DrawShadowMap)(int side, struct entity_render_s *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist, const unsigned char *surfacesides, const vec3_t lightmins, const vec3_t lightmaxs)
void(* GetLightInfo)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
vec3_t normalmins
int num_surfaces
void(* DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs)
vec3_t normal
Definition model_brush.h:59
vec_t dist
Definition model_brush.h:60
describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling.
vec3_t mins
bounding box for onscreen checks
r_waterstate_t water
Definition render.h:898
float lightmapintensity
Definition render.h:387
float rtlightstylevalue[MAX_LIGHTSTYLES]
float fraction of base light value
Definition render.h:377
entity_render_t ** entities
renderable entities (excluding world)
Definition render.h:361
model_t * worldmodel
same as worldentity->model
Definition render.h:358
qbool rtworldshadows
Definition render.h:390
qbool rtdlightshadows
Definition render.h:392
unsigned short lightstylevalue[MAX_LIGHTSTYLES]
8.8 fraction of base light value
Definition render.h:380
entity_render_t * worldentity
the world
Definition render.h:355
rtlight_t * lights[MAX_DLIGHTS]
Definition render.h:372
r_refdef_viewcache_t viewcache
Definition render.h:407
float polygonoffset
Definition render.h:459
r_refdef_view_t view
Definition render.h:406
double farclip
Definition render.h:413
int stats[r_stat_count]
Definition render.h:466
r_refdef_scene_t scene
Definition render.h:418
double nearclip
Definition render.h:410
float polygonfactor
Definition render.h:458
float colorscale
global RGB color multiplier for rendering
Definition render.h:302
qbool showdebug
Definition render.h:314
vec3_t right
Definition render.h:270
int cullface_back
Definition render.h:318
vec3_t origin
Definition render.h:267
int useperspective
if turned off it renders an ortho view
Definition render.h:280
mplane_t frustum[6]
Definition render.h:273
r_viewport_t viewport
note: if r_viewscale is used, the viewport.width and viewport.height may be less than width and heigh...
Definition render.h:296
int colormask[4]
which color components to allow (for anaglyph glasses)
Definition render.h:299
int cullface_front
Definition render.h:317
vec3_t frustumcorner[4]
Definition render.h:278
vec3_t forward
Definition render.h:268
unsigned char * world_leafvisible
Definition render.h:341
unsigned char * entityvisible
which entities are currently visible for this viewpoint (the used range is 0...r_refdef....
Definition render.h:336
r_shadow_bouncegrid_photon_path_t paths[PHOTON_MAX_PATHS]
Definition r_shadow.h:89
taskqueue_task_t enqueuephotons_task
Definition r_shadow.h:128
taskqueue_task_t enqueue_slices_task
Definition r_shadow.h:131
taskqueue_task_t photons_done_task
Definition r_shadow.h:130
taskqueue_task_t slices_done_task
Definition r_shadow.h:133
taskqueue_task_t * photons_tasks
Definition r_shadow.h:129
unsigned char * u8pixels
Definition r_shadow.h:119
r_shadow_bouncegrid_settings_t settings
Definition r_shadow.h:95
taskqueue_task_t cleartex_task
Definition r_shadow.h:126
unsigned short * fp16pixels
Definition r_shadow.h:120
taskqueue_task_t * slices_tasks
Definition r_shadow.h:132
taskqueue_task_t blurpixels_task
Definition r_shadow.h:134
r_shadow_bouncegrid_photon_t * photons
Definition r_shadow.h:123
taskqueue_task_t assignphotons_task
Definition r_shadow.h:127
struct rtexture_s * texture
Definition r_shadow.h:100
matrix4x4_t projectmatrix
actual projection matrix (transforms from viewspace to screen)
Definition render.h:242
matrix4x4_t viewmatrix
actual matrix for rendering (transforms to viewspace)
Definition render.h:241
qbool renderingscene
Definition render.h:876
const rtlight_t * rtlight
Definition render.h:748
matrix4x4_t entitytolight
Definition render.h:754
matrix4x4_t entitytoattenuationz
Definition render.h:759
int batchnumvertices
Definition render.h:670
texture_t * texture
Definition render.h:733
entity_render_t * entity
Definition render.h:767
vec3_t entitylightorigin
Definition render.h:751
matrix4x4_t entitytoattenuationxyz
Definition render.h:757
float * batchvertex3f
Definition render.h:673
vec_t ambientscale
ambient intensity to render
Definition client.h:128
rtexture_t * currentcubemap
this is R_GetCubemap(rtlight->cubemapname)
Definition client.h:153
vec3_t currentcolor
Definition client.h:147
struct entity_render_s ** cached_lightentities_noselfshadow
Definition client.h:165
vec3_t cached_cullmins
Definition client.h:172
float corona_visibility
used by corona updates, due to occlusion query
Definition client.h:149
unsigned char * static_shadowtrispvs
Definition client.h:208
int shadowmapatlassidesize
size of one side of this light in the shadowmap atlas (for omnidirectional shadowmaps this is the min...
Definition client.h:190
int shadow
whether light should render shadows (see castshadows for whether it actually does this frame)
Definition client.h:122
int static_shadowmap_receivers
masks of all shadowmap sides that have any potential static receivers or casters
Definition client.h:215
int cached_numlightentities
these fields are set by R_Shadow_PrepareLight for later drawing
Definition client.h:159
int bouncegrid_traces
Definition client.h:227
unsigned char * static_leafpvs
Definition client.h:197
vec3_t color
typically 1 1 1, can be lower (dim) or higher (overbright)
Definition client.h:114
int static_shadowmap_casters
Definition client.h:216
double trace_timer
when r_shadow_culllights_trace is set, this is refreshed by each successful trace.
Definition client.h:143
unsigned char * cached_shadowtrispvs
Definition client.h:168
vec_t corona
intensity of corona to render
Definition client.h:124
int static_numleafpvsbytes
Definition client.h:195
vec_t specularscale
specular intensity to render
Definition client.h:132
unsigned int corona_queryindex_visiblepixels
Definition client.h:150
int cached_numlightentities_noselfshadow
Definition client.h:160
vec3_t cullmins
culling
Definition client.h:140
int flags
LIGHTFLAG_* flags.
Definition client.h:134
mplane_t cached_frustumplanes[5]
Definition client.h:178
int compiled
true if this is a compiled world light, cleared if the light changes
Definition client.h:184
unsigned char * static_lighttrispvs
Definition client.h:213
int cached_numshadowentities
Definition client.h:161
int style
light style to monitor for brightness
Definition client.h:120
qbool draw
set by R_Shadow_PrepareLight to decide whether R_Shadow_DrawLight should draw it
Definition client.h:155
shadowmesh_t * static_meshchain_shadow_shadowmap
optimized and culled mesh to render for world entity shadows
Definition client.h:192
int cached_numfrustumplanes
Definition client.h:177
vec3_t shadoworigin
used only for casting shadows
Definition client.h:138
float bouncegrid_effectiveradius
Definition client.h:228
int isstatic
static light info true if this light should be compiled as a static light
Definition client.h:182
int static_numlighttrispvsbytes
this allows the lighting batch code to skip backfaces andother culled triangles not relevant for ligh...
Definition client.h:212
vec_t coronasizescale
radius scale of corona to render (1.0 means same as light radius)
Definition client.h:126
int * static_leaflist
Definition client.h:196
char cubemapname[64]
light filter
Definition client.h:118
int static_numsurfaces
surfaces seen by light
Definition client.h:199
int shadowmapsidesize
the size that this light should have (assuming no scene LOD kicking in to reduce it)
Definition client.h:186
matrix4x4_t matrix_lighttoworld
matrix for transforming light filter coordinates to world coordinates
Definition client.h:110
int cached_numsurfaces
Definition client.h:163
vec3_t cullmaxs
Definition client.h:141
struct entity_render_s ** cached_shadowentities_noselfshadow
Definition client.h:167
matrix4x4_t matrix_worldtolight
matrix for transforming world coordinates to light filter coordinates
Definition client.h:112
int static_numshadowtrispvsbytes
flag bits indicating which triangles of the world model should cast shadows, and which ones should be...
Definition client.h:207
int bouncegrid_hits
Definition client.h:226
float bouncegrid_photons
Definition client.h:225
float bouncegrid_photoncolor[3]
bouncegrid light info
Definition client.h:224
vec_t diffusescale
diffuse intensity to render
Definition client.h:130
struct entity_render_s ** cached_lightentities
Definition client.h:164
int static_numleafs
used for visibility testing (more exact than bbox)
Definition client.h:194
int cached_numshadowentities_noselfshadow
Definition client.h:162
int * cached_surfacelist
Definition client.h:170
unsigned char * cached_lighttrispvs
Definition client.h:169
qbool castshadows
set by R_Shadow_PrepareLight to indicate whether R_Shadow_DrawShadowMaps should do anything
Definition client.h:157
vec_t radius
size of the light (remove?)
Definition client.h:116
int * static_surfacelist
Definition client.h:200
int shadowmapatlasposition[2]
position of this light in the shadowmap atlas
Definition client.h:188
struct entity_render_s ** cached_shadowentities
Definition client.h:166
unsigned int corona_queryindex_allpixels
Definition client.h:151
vec3_t cached_cullmaxs
Definition client.h:173
int element3s_bufferoffset
int sidetotals[6]
int element3i_bufferoffset
r_meshbuffer_t * element3s_indexbuffer
r_meshbuffer_t * vbo_vertexbuffer
int sideoffsets[6]
float * vertex3f
r_meshbuffer_t * element3i_indexbuffer
unsigned short * element3s
int num_triangles
void * p[2]
Definition taskqueue.h:19
size_t i[2]
Definition taskqueue.h:20
volatile int done
Definition taskqueue.h:14
void(* func)(struct taskqueue_task_s *task)
Definition taskqueue.h:17
float render_rtlight_specular[3]
int currentmaterialflags
float render_rtlight_diffuse[3]
float rtlightambient
const struct texture_s * hittexture
Definition collision.h:62
double fraction
Definition collision.h:40
const struct texture_s * starttexture
Definition collision.h:70
double endpos[3]
Definition collision.h:42
int startsupercontents
Definition collision.h:56
plane_t plane
Definition collision.h:44
qbool amd_texture_texture4
Definition vid.h:46
qbool arb_texture_gather
Definition vid.h:47
int glversion
this is at least 32
Definition vid.h:44
unsigned int maxtexturesize_2d
Definition vid.h:83
unsigned int maxtexturesize_3d
Definition vid.h:84
renderpath_t renderpath
Definition vid.h:80
viddef_support_t support
Definition vid.h:89
unsigned int maxdrawbuffers
Definition vid.h:87
void TaskQueue_Yield(taskqueue_task_t *t)
Definition taskqueue.c:133
void TaskQueue_WaitForTaskDone(taskqueue_task_t *t)
Definition taskqueue.c:199
void TaskQueue_Setup(taskqueue_task_t *t, taskqueue_task_t *preceding, void(*func)(taskqueue_task_t *), size_t i0, size_t i1, void *p0, void *p1)
Definition taskqueue.c:282
void TaskQueue_Enqueue(int numtasks, taskqueue_task_t *tasks)
Definition taskqueue.c:105
void TaskQueue_Task_CheckTasksDone(taskqueue_task_t *t)
Definition taskqueue.c:293
vec3_t normal
Definition collision.h:13
const char * gl_vendor
brand of graphics chip
Definition vid_shared.c:190
@ RENDERPATH_GLES2
Definition vid.h:38
@ RENDERPATH_GL32
Definition vid.h:37
const char * gl_version
begins with 1.0.0, 1.1.0, 1.2.0, 1.2.1, 1.3.0, 1.3.1, or 1.4.0
Definition vid_shared.c:194
const char * gl_renderer
graphics chip model and other information
Definition vid_shared.c:192
viddef_t vid
global video state
Definition vid_shared.c:64
#define MOVE_HITMODEL
Definition world.h:32
#define MOVE_WORLDONLY
Definition world.h:31
#define MOVE_NORMAL
Definition world.h:28
#define MOVE_NOMONSTERS
Definition world.h:29
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
Definition zone.c:675
void Mem_ExpandableArray_FreeRecord(memexpandablearray_t *l, void *record)
Definition zone.c:743
void * Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l)
Definition zone.c:695
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92
#define Z_Malloc(size)
Definition zone.h:161
#define Mem_Realloc(pool, data, size)
Definition zone.h:94
#define Z_Free(data)
Definition zone.h:164