cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
-cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
+cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect OpenGL 2.0 render path)"};
-cvar_t r_shadow_particletrace = {CVAR_SAVE, "r_shadow_particletrace", "0", "perform particle tracing for indirect lighting (Global Illumination / radiosity), requires r_shadow_deferred 1, requires r_shadow_realtime_world 1, EXTREMELY SLOW"};
-cvar_t r_shadow_particletrace_intensity = {CVAR_SAVE, "r_shadow_particletrace_intensity", "128", "overall brightness of particle traced radiosity"};
-cvar_t r_shadow_particletrace_size = {CVAR_SAVE, "r_shadow_particletrace_size", "32", "particles produce bounce lights of this radius"};
-cvar_t r_shadow_particletrace_radiusscale = {CVAR_SAVE, "r_shadow_particletrace_radiusscale", "1", "particles stop at this fraction of light radius"};
-cvar_t r_shadow_particletrace_maxbounce = {CVAR_SAVE, "r_shadow_particletrace_maxbounce", "1", "maximum number of bounces for a particle (minimum is 1)"};
-cvar_t r_shadow_particletrace_bounceintensity = {CVAR_SAVE, "r_shadow_particletrace_bounceintensity", "1", "amount of energy carried over after each bounce"};
-cvar_t r_shadow_particletrace_particlespacing = {CVAR_SAVE, "r_shadow_particletrace_particlespacing", "0.25", "overlap setting in terms of particle size, this affects how many particles are used"};
-cvar_t r_shadow_particletrace_updatepercentage = {CVAR_SAVE, "r_shadow_particletrace_updatepercentage", "0.01", "update this fraction of the particles of a light each frame (0 = best performance)"};
cvar_t r_shadow_bouncegrid = {CVAR_SAVE, "r_shadow_bouncegrid", "0", "perform particle tracing for indirect lighting (Global Illumination / radiosity) using a 3D texture covering the scene, requires r_shadow_realtime_world 1"};
cvar_t r_shadow_bouncegrid_bounceanglediffuse = {CVAR_SAVE, "r_shadow_bouncegrid_bounceanglediffuse", "0", "use random bounce direction rather than true reflection, makes some corner areas dark"};
cvar_t r_shadow_bouncegrid_dlightparticlemultiplier = {CVAR_SAVE, "r_shadow_bouncegrid_dlightparticlemultiplier", "0", "if set to a high value like 16 this can make dlights look great, but 0 is recommended for performance reasons"};
cvar_t r_shadow_bouncegrid_hitmodels = {CVAR_SAVE, "r_shadow_bouncegrid_hitmodels", "0", "enables hitting character model geometry (SLOW)"};
-cvar_t r_shadow_bouncegrid_intensity = {CVAR_SAVE, "r_shadow_bouncegrid_intensity", "1", "overall brightness of bouncegrid texture"};
+cvar_t r_shadow_bouncegrid_intensity = {CVAR_SAVE, "r_shadow_bouncegrid_intensity", "4", "overall brightness of bouncegrid texture"};
cvar_t r_shadow_bouncegrid_lightradiusscale = {CVAR_SAVE, "r_shadow_bouncegrid_lightradiusscale", "2", "particles stop at this fraction of light radius (can be more than 1)"};
cvar_t r_shadow_bouncegrid_maxbounce = {CVAR_SAVE, "r_shadow_bouncegrid_maxbounce", "3", "maximum number of bounces for a particle (minimum is 1)"};
-cvar_t r_shadow_bouncegrid_particlebounceintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particlebounceintensity", "1", "amount of energy carried over after each bounce"};
-cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "4", "brightness of particles contributing to bouncegrid texture"};
-cvar_t r_shadow_bouncegrid_particlespacing = {CVAR_SAVE, "r_shadow_bouncegrid_particlespacing", "32", "emit one particle per this many units (squared) of radius (squared)"};
+cvar_t r_shadow_bouncegrid_nolerpsplat = {CVAR_SAVE, "r_shadow_bouncegrid_nolerpsplat", "0", "enables slightly quicker (but worse looking) photon accumulation"};
+cvar_t r_shadow_bouncegrid_particlebounceintensity = {CVAR_SAVE, "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"};
+cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "2", "brightness of particles contributing to bouncegrid texture"};
+cvar_t r_shadow_bouncegrid_photons = {CVAR_SAVE, "r_shadow_bouncegrid_photons", "5000", "total photons to shoot per update, divided proportionately between lights"};
cvar_t r_shadow_bouncegrid_spacingx = {CVAR_SAVE, "r_shadow_bouncegrid_spacingx", "64", "unit size of bouncegrid pixel on X axis"};
cvar_t r_shadow_bouncegrid_spacingy = {CVAR_SAVE, "r_shadow_bouncegrid_spacingy", "64", "unit size of bouncegrid pixel on Y axis"};
cvar_t r_shadow_bouncegrid_spacingz = {CVAR_SAVE, "r_shadow_bouncegrid_spacingz", "64", "unit size of bouncegrid pixel on Z axis"};
Cvar_RegisterVariable(&r_shadow_polygonfactor);
Cvar_RegisterVariable(&r_shadow_polygonoffset);
Cvar_RegisterVariable(&r_shadow_texture3d);
- Cvar_RegisterVariable(&r_shadow_particletrace);
- Cvar_RegisterVariable(&r_shadow_particletrace_intensity);
- Cvar_RegisterVariable(&r_shadow_particletrace_size);
- Cvar_RegisterVariable(&r_shadow_particletrace_radiusscale);
- Cvar_RegisterVariable(&r_shadow_particletrace_maxbounce);
- Cvar_RegisterVariable(&r_shadow_particletrace_bounceintensity);
- Cvar_RegisterVariable(&r_shadow_particletrace_particlespacing);
- Cvar_RegisterVariable(&r_shadow_particletrace_updatepercentage);
Cvar_RegisterVariable(&r_shadow_bouncegrid);
Cvar_RegisterVariable(&r_shadow_bouncegrid_bounceanglediffuse);
Cvar_RegisterVariable(&r_shadow_bouncegrid_dlightparticlemultiplier);
Cvar_RegisterVariable(&r_shadow_bouncegrid_intensity);
Cvar_RegisterVariable(&r_shadow_bouncegrid_lightradiusscale);
Cvar_RegisterVariable(&r_shadow_bouncegrid_maxbounce);
+ Cvar_RegisterVariable(&r_shadow_bouncegrid_nolerpsplat);
Cvar_RegisterVariable(&r_shadow_bouncegrid_particlebounceintensity);
Cvar_RegisterVariable(&r_shadow_bouncegrid_particleintensity);
- Cvar_RegisterVariable(&r_shadow_bouncegrid_particlespacing);
+ Cvar_RegisterVariable(&r_shadow_bouncegrid_photons);
Cvar_RegisterVariable(&r_shadow_bouncegrid_spacingx);
Cvar_RegisterVariable(&r_shadow_bouncegrid_spacingy);
Cvar_RegisterVariable(&r_shadow_bouncegrid_spacingz);
int hitsupercontentsmask;
int maxbounce;
int numpixels;
- int pixelindex;
int resolution[3];
int shootparticles;
int shotparticles;
+ int photoncount;
int tex[3];
trace_t cliptrace;
+ //trace_t cliptrace2;
+ //trace_t cliptrace3;
unsigned char *pixel;
unsigned char *pixels;
unsigned short *highpixel;
unsigned int seed = (unsigned int)(realtime * 1000.0f);
vec3_t shotcolor;
vec3_t baseshotcolor;
+ vec3_t surfcolor;
vec3_t clipend;
vec3_t clipstart;
vec3_t clipdiff;
vec_t radius;
vec_t s;
vec_t lightintensity;
+ vec_t photonscaling;
+ vec_t photonresidual;
float m[16];
+ int texlerp[2][3];
+ int splatcolor[3];
+ int pixelindex[8];
+ int pixelweight[8];
+ int corner;
qboolean isstatic = r_shadow_bouncegrid_updateinterval.value > 1.0f;
rtlight_t *rtlight;
if (!r_shadow_bouncegrid.integer || !vid.support.ext_texture_3d)
range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
range1 = isstatic ? 0 : r_refdef.scene.numlights;
range2 = range + range1;
+ photoncount = 0;
for (lightindex = 0;lightindex < range2;lightindex++)
{
if (isstatic)
// distribution, the seeded random is only consistent for a
// consistent number of particles on this light...
radius = rtlight->radius * bound(0.0001f, r_shadow_bouncegrid_lightradiusscale.value, 1024.0f);
- s = rtlight->radius / bound(1.0f, r_shadow_bouncegrid_particlespacing.value, 1048576.0f);
- lightintensity = VectorLength(rtlight->color) * rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale;
+ s = rtlight->radius;
+ lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
if (lightindex >= range)
lightintensity *= r_shadow_bouncegrid_dlightparticlemultiplier.value;
- shootparticles = (int)bound(0, lightintensity * s *s, MAXBOUNCEGRIDPARTICLESPERLIGHT);
+ photoncount += max(0.0f, lightintensity * s * s);
+ }
+ photonscaling = bound(1, r_shadow_bouncegrid_photons.value, 1048576) / max(1, photoncount);
+ photonresidual = 0.0f;
+ for (lightindex = 0;lightindex < range2;lightindex++)
+ {
+ if (isstatic)
+ {
+ light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+ if (!light || !(light->flags & flag))
+ continue;
+ rtlight = &light->rtlight;
+ // when static, we skip styled lights because they tend to change...
+ if (rtlight->style > 0)
+ continue;
+ VectorScale(rtlight->color, (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) * (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1), lightcolor);
+ }
+ else
+ {
+ if (lightindex < range)
+ {
+ light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+ rtlight = &light->rtlight;
+ }
+ else
+ rtlight = r_refdef.scene.lights[lightindex - range];
+ // draw only visible lights (major speedup)
+ if (!rtlight->draw)
+ continue;
+ VectorScale(rtlight->currentcolor, rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale, lightcolor);
+ }
+ if (!VectorLength2(lightcolor))
+ continue;
+ // shoot particles from this light
+ // use a calculation for the number of particles that will not
+ // vary with lightstyle, otherwise we get randomized particle
+ // distribution, the seeded random is only consistent for a
+ // consistent number of particles on this light...
+ radius = rtlight->radius * bound(0.0001f, r_shadow_bouncegrid_lightradiusscale.value, 1024.0f);
+ s = rtlight->radius;
+ lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
+ if (lightindex >= range)
+ lightintensity *= r_shadow_bouncegrid_dlightparticlemultiplier.value;
+ photonresidual += lightintensity * s * s * photonscaling;
+ shootparticles = (int)bound(0, photonresidual, MAXBOUNCEGRIDPARTICLESPERLIGHT);
if (!shootparticles)
continue;
+ photonresidual -= shootparticles;
s = 65535.0f * r_shadow_bouncegrid_particleintensity.value / shootparticles;
VectorScale(lightcolor, s, baseshotcolor);
if (VectorLength2(baseshotcolor) < 3.0f)
for (bouncecount = 0;;bouncecount++)
{
r_refdef.stats.bouncegrid_traces++;
- cliptrace = CL_TraceLine(clipstart, clipend, r_shadow_bouncegrid_hitmodels.integer ? MOVE_HITMODEL : MOVE_NOMONSTERS, NULL, hitsupercontentsmask, true, false, NULL, true);
+ //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
+ //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
+ cliptrace = CL_TraceLine(clipstart, clipend, r_shadow_bouncegrid_hitmodels.integer ? MOVE_HITMODEL : MOVE_NOMONSTERS, NULL, hitsupercontentsmask, true, false, NULL, true, true);
//Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask);
if (cliptrace.fraction >= 1.0f)
break;
{
r_refdef.stats.bouncegrid_splats++;
// figure out which texture pixel this is in
- tex[0] = (int)((cliptrace.endpos[0] - mins[0]) * ispacing[0]);
- tex[1] = (int)((cliptrace.endpos[1] - mins[1]) * ispacing[1]);
- tex[2] = (int)((cliptrace.endpos[2] - mins[2]) * ispacing[2]);
- if (tex[0] >= 1 && tex[1] >= 1 && tex[2] >= 1 && tex[0] < resolution[0] - 1 && tex[1] < resolution[1] - 1 && tex[2] < resolution[2] - 1)
+ texlerp[1][0] = (int)(((cliptrace.endpos[0] - mins[0]) * ispacing[0]) * 256.0f);
+ texlerp[1][1] = (int)(((cliptrace.endpos[1] - mins[1]) * ispacing[1]) * 256.0f);
+ texlerp[1][2] = (int)(((cliptrace.endpos[2] - mins[2]) * ispacing[2]) * 256.0f);
+ tex[0] = texlerp[1][0] >> 8;
+ tex[1] = texlerp[1][1] >> 8;
+ tex[2] = texlerp[1][2] >> 8;
+ if (tex[0] >= 1 && tex[1] >= 1 && tex[2] >= 1 && tex[0] < resolution[0] - 2 && tex[1] < resolution[1] - 2 && tex[2] < resolution[2] - 2)
{
// it is within bounds...
- pixelindex = ((tex[2]*resolution[1]+tex[1])*resolution[0]+tex[0]);
- pixel = pixels + 4 * pixelindex;
- highpixel = highpixels + 3 * pixelindex;
- // add to the high precision pixel color
- c[0] = highpixel[0] + (int)shotcolor[2];
- c[1] = highpixel[1] + (int)shotcolor[1];
- c[2] = highpixel[2] + (int)shotcolor[0];
- highpixel[0] = (unsigned short)min(c[0], 65535);
- highpixel[1] = (unsigned short)min(c[1], 65535);
- highpixel[2] = (unsigned short)min(c[2], 65535);
- // update the low precision pixel color
- pixel[0] = highpixel[0] >> 8;
- pixel[1] = highpixel[1] >> 8;
- pixel[2] = highpixel[2] >> 8;
- pixel[3] = 255;
+ splatcolor[0] = (int)shotcolor[2];
+ splatcolor[1] = (int)shotcolor[1];
+ splatcolor[2] = (int)shotcolor[0];
+ // calculate the lerp factors
+ if (r_shadow_bouncegrid_nolerpsplat.integer)
+ {
+ pixelindex[0] = (((tex[2] )*resolution[1]+tex[1] )*resolution[0]+tex[0] );
+ pixel = pixels + 4 * pixelindex[0];
+ highpixel = highpixels + 3 * pixelindex[0];
+ // add to the high precision pixel color
+ c[0] = highpixel[0] + splatcolor[0];
+ c[1] = highpixel[1] + splatcolor[1];
+ c[2] = highpixel[2] + splatcolor[2];
+ highpixel[0] = (unsigned short)min(c[0], 65535);
+ highpixel[1] = (unsigned short)min(c[1], 65535);
+ highpixel[2] = (unsigned short)min(c[2], 65535);
+ // update the low precision pixel color
+ pixel[0] = highpixel[0] >> 8;
+ pixel[1] = highpixel[1] >> 8;
+ pixel[2] = highpixel[2] >> 8;
+ pixel[3] = 255;
+ }
+ else
+ {
+ texlerp[1][0] &= 0xFF;
+ texlerp[1][1] &= 0xFF;
+ texlerp[1][2] &= 0xFF;
+ texlerp[0][0] = 256 - texlerp[1][0];
+ texlerp[0][1] = 256 - texlerp[1][1];
+ texlerp[0][2] = 256 - texlerp[1][2];
+ // calculate individual pixel indexes and weights
+ pixelindex[0] = (((tex[2] )*resolution[1]+tex[1] )*resolution[0]+tex[0] );pixelweight[0] = (texlerp[0][0]*texlerp[0][1]*texlerp[0][2]) >> 16;
+ pixelindex[1] = (((tex[2] )*resolution[1]+tex[1] )*resolution[0]+tex[0]+1);pixelweight[1] = (texlerp[1][0]*texlerp[0][1]*texlerp[0][2]) >> 16;
+ pixelindex[2] = (((tex[2] )*resolution[1]+tex[1]+1)*resolution[0]+tex[0] );pixelweight[2] = (texlerp[0][0]*texlerp[1][1]*texlerp[0][2]) >> 16;
+ pixelindex[3] = (((tex[2] )*resolution[1]+tex[1]+1)*resolution[0]+tex[0]+1);pixelweight[3] = (texlerp[1][0]*texlerp[1][1]*texlerp[0][2]) >> 16;
+ pixelindex[4] = (((tex[2]+1)*resolution[1]+tex[1] )*resolution[0]+tex[0] );pixelweight[4] = (texlerp[0][0]*texlerp[0][1]*texlerp[1][2]) >> 16;
+ pixelindex[5] = (((tex[2]+1)*resolution[1]+tex[1] )*resolution[0]+tex[0]+1);pixelweight[5] = (texlerp[1][0]*texlerp[0][1]*texlerp[1][2]) >> 16;
+ pixelindex[6] = (((tex[2]+1)*resolution[1]+tex[1]+1)*resolution[0]+tex[0] );pixelweight[6] = (texlerp[0][0]*texlerp[1][1]*texlerp[1][2]) >> 16;
+ pixelindex[7] = (((tex[2]+1)*resolution[1]+tex[1]+1)*resolution[0]+tex[0]+1);pixelweight[7] = (texlerp[1][0]*texlerp[1][1]*texlerp[1][2]) >> 16;
+ // update the 8 pixels...
+ for (corner = 0;corner < 8;corner++)
+ {
+ pixel = pixels + 4 * pixelindex[corner];
+ highpixel = highpixels + 3 * pixelindex[corner];
+ // add to the high precision pixel color
+ c[0] = highpixel[0] + ((splatcolor[0]*pixelweight[corner])>>8);
+ c[1] = highpixel[1] + ((splatcolor[1]*pixelweight[corner])>>8);
+ c[2] = highpixel[2] + ((splatcolor[2]*pixelweight[corner])>>8);
+ highpixel[0] = (unsigned short)min(c[0], 65535);
+ highpixel[1] = (unsigned short)min(c[1], 65535);
+ highpixel[2] = (unsigned short)min(c[2], 65535);
+ // update the low precision pixel color
+ pixel[0] = highpixel[0] >> 8;
+ pixel[1] = highpixel[1] >> 8;
+ pixel[2] = highpixel[2] >> 8;
+ pixel[3] = 255;
+ }
+ }
}
}
if (bouncecount >= maxbounce)
break;
// scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
- VectorScale(shotcolor, r_shadow_bouncegrid_particlebounceintensity.value, shotcolor);
+ // also clamp the resulting color to never add energy, even if the user requests extreme values
if (cliptrace.hittexture && cliptrace.hittexture->currentskinframe)
- VectorMultiply(shotcolor, rsurface.texture->currentskinframe->avgcolor, shotcolor);
+ VectorCopy(cliptrace.hittexture->currentskinframe->avgcolor, surfcolor);
else
- VectorScale(shotcolor, 0.5f->avgcolor, shotcolor);
+ VectorSet(surfcolor, 0.5f, 0.5f, 0.5f);
+ VectorScale(surfcolor, r_shadow_bouncegrid_particlebounceintensity.value, surfcolor);
+ surfcolor[0] = min(surfcolor[0], 1.0f);
+ surfcolor[1] = min(surfcolor[1], 1.0f);
+ surfcolor[2] = min(surfcolor[2], 1.0f);
+ VectorMultiply(shotcolor, surfcolor, shotcolor);
if (VectorLength2(shotcolor) < 3.0f)
break;
r_refdef.stats.bouncegrid_bounces++;
r_shadow_bouncegridtime = realtime;
}
-#define MAXPARTICLESPERLIGHT 262144
-#define MAXLIGHTSPERDRAW 1024
-
-static void R_Shadow_RenderParticlesForLight(rtlight_t *rtlight)
-{
- int batchcount;
- int i;
- int j;
- int bouncecount;
- int hitsupercontentsmask;
- int n;
- int shotparticles;
- int shootparticles = 0;
- int bouncelimit;
- int maxbounce;
- unsigned int seed = 0;
- static unsigned short bouncelight_elements[MAXLIGHTSPERDRAW*36];
- static float vertex3f[MAXLIGHTSPERDRAW*24];
- static float lightorigin4f[MAXLIGHTSPERDRAW*32];
- static float color4f[MAXLIGHTSPERDRAW*32];
- float scaledpoints[8][3];
- float *v3f;
- float *lo4f;
- float *c4f;
- rtlight_particle_t *p;
- vec_t wantparticles = 0;
- vec_t s;
- vec_t radius;
- vec_t particlesize;
- vec_t iparticlesize;
-// vec3_t offset;
-// vec3_t right;
-// vec3_t up;
- vec4_t org;
- vec4_t color;
- vec3_t currentcolor;
- vec3_t clipstart;
- vec3_t clipend;
- vec3_t shotcolor;
- trace_t cliptrace;
- if (!rtlight->draw || !rtlight->isstatic || !r_shadow_usingdeferredprepass)
- return;
- if (r_shadow_particletrace.integer)
- {
- radius = rtlight->radius * bound(0.0001f, r_shadow_particletrace_radiusscale.value, 1.0f) - r_shadow_particletrace_size.value;
- s = rtlight->radius / bound(1.0f, r_shadow_particletrace_particlespacing.value * r_shadow_particletrace_size.value, 1048576.0f);
- wantparticles = s*s;
- n = (int)bound(0, wantparticles, MAXPARTICLESPERLIGHT);
- }
- else
- n = 0;
- shootparticles = (int)(n * r_shadow_particletrace_updatepercentage.value);
- if ((n && !rtlight->particlecache_particles) || rtlight->particlecache_maxparticles != n)
- {
- if (rtlight->particlecache_particles)
- Mem_Free(rtlight->particlecache_particles);
- rtlight->particlecache_particles = NULL;
- rtlight->particlecache_numparticles = 0;
- rtlight->particlecache_maxparticles = n;
- rtlight->particlecache_updateparticle = 0;
- if (rtlight->particlecache_maxparticles)
- rtlight->particlecache_particles = (rtlight_particle_t *)Mem_Alloc(r_main_mempool, rtlight->particlecache_maxparticles * sizeof(*rtlight->particlecache_particles));
- shootparticles = n * 16;
- }
-
- if (!rtlight->particlecache_maxparticles)
- return;
-
-// if (rtlight->particlecache_numparticles < rtlight->particlecache_maxparticles)
-// shootparticles = rtlight->particlecache_maxparticles;
-
-// if (rtlight->particlecache_numparticles >= rtlight->particlecache_maxparticles)
-// shootparticles = 0;
-
- maxbounce = bound(1, r_shadow_particletrace_maxbounce.integer, 16);
- //r_refdef.stats.lights_bouncelightsupdated += shootparticles;
- for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
- {
- seed = rtlight->particlecache_updateparticle;
- VectorSet(shotcolor, 1.0f, 1.0f, 1.0f);
- VectorCopy(rtlight->shadoworigin, clipstart);
- VectorRandom(clipend);
- VectorMA(clipstart, radius, clipend, clipend);
- hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK;
- bouncelimit = 1 + (rtlight->particlecache_updateparticle % maxbounce);
- for (bouncecount = 0;;bouncecount++)
- {
- cliptrace = CL_TraceLine(clipstart, clipend, MOVE_NOMONSTERS, NULL, hitsupercontentsmask, true, false, NULL, true);
- //Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask);
- if (cliptrace.fraction >= 1.0f)
- break;
- if (VectorLength2(shotcolor) < (1.0f / 262144.0f))
- break;
- if (bouncecount >= bouncelimit)
- {
- VectorCopy(cliptrace.endpos, rtlight->particlecache_particles[rtlight->particlecache_updateparticle].origin);
- VectorCopy(shotcolor, rtlight->particlecache_particles[rtlight->particlecache_updateparticle].color);
- rtlight->particlecache_updateparticle++;
- if (rtlight->particlecache_numparticles < rtlight->particlecache_updateparticle)
- rtlight->particlecache_numparticles = rtlight->particlecache_updateparticle;
- if (rtlight->particlecache_updateparticle >= rtlight->particlecache_maxparticles)
- {
- rtlight->particlecache_updateparticle = 0;
- shotparticles = shootparticles;
- }
- break;
- }
- // scale down shot color by bounce intensity and texture color
- VectorScale(shotcolor, r_shadow_particletrace_bounceintensity.value, shotcolor);
- if (cliptrace.hittexture && cliptrace.hittexture->currentskinframe)
- VectorMultiply(shotcolor, rsurface.texture->currentskinframe->avgcolor, shotcolor);
- // reflect the remaining portion of the line across plane normal
- //VectorSubtract(clipend, cliptrace.endpos, clipdiff);
- //VectorReflect(clipdiff, 1.0, cliptrace.plane.normal, clipend);
- // random direction, primarily along plane normal
- s = VectorDistance(cliptrace.endpos, clipend);
- VectorRandom(clipend);
- VectorMA(cliptrace.plane.normal, 0.95f, clipend, clipend);
- VectorNormalize(clipend);
- VectorScale(clipend, s, clipend);
- // calculate the new line start and end
- VectorCopy(cliptrace.endpos, clipstart);
- VectorAdd(clipstart, clipend, clipend);
- }
- }
-
- if (!rtlight->particlecache_numparticles)
- return;
-
- // render the particles as deferred lights
-// do global setup needed for the chosen lighting mode
- R_Shadow_RenderMode_Reset();
- r_shadow_rendermode = r_shadow_lightingrendermode;
- r_shadow_usingshadowmap2d = false;
- R_EntityMatrix(&identitymatrix);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- // only draw light where this geometry was already rendered AND the
- // stencil is 128 (values other than this mean shadow)
- R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
- R_SetupShader_DeferredBounceLight();
- GL_ColorMask(1,1,1,1);
- GL_DepthMask(false);
- GL_DepthRange(0, 1);
- GL_PolygonOffset(0, 0);
- GL_DepthTest(true);
- GL_DepthFunc(GL_GREATER);
- GL_CullFace(r_refdef.view.cullface_back);
- s = r_shadow_particletrace_intensity.value / (float)rtlight->particlecache_numparticles;
- VectorScale(rtlight->currentcolor, s, currentcolor);
- particlesize = bound(0.0001f, r_shadow_particletrace_size.value, 1024.0f);
- iparticlesize = 1.0f / particlesize;
-// VectorScale(r_refdef.view.forward, particlesize, offset);
-// VectorScale(r_refdef.view.left, -particlesize, right);
-// VectorScale(r_refdef.view.up, particlesize, up);
- org[3] = iparticlesize;
- color[3] = 1.0f;
- v3f = vertex3f;
- lo4f = lightorigin4f;
- c4f = color4f;
- batchcount = 0;
- if (!bouncelight_elements[1])
- for (i = 0;i < MAXLIGHTSPERDRAW;i++)
- for (j = 0;j < 36;j++)
- bouncelight_elements[i*36+j] = i*8+bboxelements[j];
- for (j = 0;j < 8;j++)
- VectorScale(bboxpoints[j], particlesize, scaledpoints[j]);
- //r_refdef.stats.lights_bouncelightscounted += rtlight->particlecache_numparticles;
- for (j = 0, p = rtlight->particlecache_particles, n = rtlight->particlecache_numparticles;j < n;j++, p++)
- {
- VectorCopy(p->origin, org);
- // org[3] is set above
- VectorMultiply(p->color, currentcolor, color);
- // color[3] is set above
- VectorAdd(scaledpoints[0], org, v3f + 0);
- VectorAdd(scaledpoints[1], org, v3f + 3);
- VectorAdd(scaledpoints[2], org, v3f + 6);
- VectorAdd(scaledpoints[3], org, v3f + 9);
- VectorAdd(scaledpoints[4], org, v3f + 12);
- VectorAdd(scaledpoints[5], org, v3f + 15);
- VectorAdd(scaledpoints[6], org, v3f + 18);
- VectorAdd(scaledpoints[7], org, v3f + 21);
- Vector4Copy(org, lo4f + 0);
- Vector4Copy(org, lo4f + 4);
- Vector4Copy(org, lo4f + 8);
- Vector4Copy(org, lo4f + 12);
- Vector4Copy(org, lo4f + 16);
- Vector4Copy(org, lo4f + 20);
- Vector4Copy(org, lo4f + 24);
- Vector4Copy(org, lo4f + 28);
- Vector4Copy(color, c4f + 0);
- Vector4Copy(color, c4f + 4);
- Vector4Copy(color, c4f + 8);
- Vector4Copy(color, c4f + 12);
- Vector4Copy(color, c4f + 16);
- Vector4Copy(color, c4f + 20);
- Vector4Copy(color, c4f + 24);
- Vector4Copy(color, c4f + 28);
- v3f += 24;
- lo4f += 32;
- c4f += 32;
- batchcount++;
- if (batchcount >= MAXLIGHTSPERDRAW)
- {
- //r_refdef.stats.lights_bouncelightsdrawn += batchcount;
- R_Mesh_PrepareVertices_BounceLight_Arrays(batchcount*8, vertex3f, color4f, lightorigin4f);
- R_Mesh_Draw(0, batchcount*8, 0, batchcount*12, NULL, NULL, 0, bouncelight_elements, NULL, 0);
- v3f = vertex3f;
- lo4f = lightorigin4f;
- c4f = color4f;
- batchcount = 0;
- }
- }
- if (batchcount)
- {
- //r_refdef.stats.lights_bouncelightsdrawn += batchcount;
- R_Mesh_PrepareVertices_BounceLight_Arrays(batchcount*8, vertex3f, color4f, lightorigin4f);
- R_Mesh_Draw(0, batchcount*8, 0, batchcount*12, NULL, NULL, 0, bouncelight_elements, NULL, 0);
- v3f = vertex3f;
- lo4f = lightorigin4f;
- c4f = color4f;
- batchcount = 0;
- }
-}
-
void R_Shadow_RenderMode_VisibleShadowVolumes(void)
{
R_Shadow_RenderMode_Reset();
else
R_Shadow_RenderMode_DrawDeferredLight(false, false);
}
-
- if (r_shadow_particletrace.integer)
- R_Shadow_RenderParticlesForLight(rtlight);
}
static void R_Shadow_FreeDeferred(void)
else
{
// FIXME: these traces should scan all render entities instead of cl.world
- if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
+ if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
return;
}
VectorScale(rtlight->currentcolor, cscale, color);
if (rating >= 0.95)
{
rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
- if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1.0f)
+ if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1.0f)
{
bestrating = rating;
best = light;
vec3_t dest, endpos;
trace_t trace;
VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
- trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
+ trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true);
if (trace.fraction < 1)
{
dist = trace.fraction * r_editlights_cursordistance.value;
intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;
intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;