152 lines
5.7 KiB
C
152 lines
5.7 KiB
C
const vec2 poissonDisk[16] = vec2[](
|
|
vec2( -0.94201624, -0.39906216 ),
|
|
vec2( 0.94558609, -0.76890725 ),
|
|
vec2( -0.094184101, -0.92938870 ),
|
|
vec2( 0.34495938, 0.29387760 ),
|
|
vec2( -0.91588581, 0.45771432 ),
|
|
vec2( -0.81544232, -0.87912464 ),
|
|
vec2( -0.38277543, 0.27676845 ),
|
|
vec2( 0.97484398, 0.75648379 ),
|
|
vec2( 0.44323325, -0.97511554 ),
|
|
vec2( 0.53742981, -0.47373420 ),
|
|
vec2( -0.26496911, -0.41893023 ),
|
|
vec2( 0.79197514, 0.19090188 ),
|
|
vec2( -0.24188840, 0.99706507 ),
|
|
vec2( -0.81409955, 0.91437590 ),
|
|
vec2( 0.19984126, 0.78641367 ),
|
|
vec2( 0.14383161, -0.14100790 )
|
|
);
|
|
|
|
#ifndef SHADOW_SAMPLES
|
|
#define SHADOW_SAMPLES ubo.settings.lighting.shadowSamples
|
|
#endif
|
|
#if VXGI
|
|
float shadowFactorVXGI( const Light, float def );
|
|
#endif
|
|
#if RT
|
|
float shadowFactorRT( const Light, float def );
|
|
#endif
|
|
|
|
#if CUBEMAPS
|
|
float omniShadowMap( const Light light, float def ) {
|
|
return 1.0;
|
|
}
|
|
#else
|
|
float omniShadowMap( const Light light, float def ) {
|
|
float factor = 1.0;
|
|
|
|
const mat4 views[6] = {
|
|
mat4( 0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1 ),
|
|
mat4( 0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 ),
|
|
mat4( 1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1 ),
|
|
mat4( 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ),
|
|
mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ),
|
|
mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1 ),
|
|
};
|
|
|
|
const vec3 D = normalize(surface.position.world - light.position);
|
|
const vec3 N = abs(D);
|
|
uint A = N.y > N.x ? 1 : 0;
|
|
A = N.z > N[A] ? 2 : A;
|
|
uint index = A * 2;
|
|
if ( D[A] < 0.0 ) ++index;
|
|
|
|
vec4 positionClip = light.projection * views[index] * vec4(surface.position.world - light.position, 1.0);
|
|
positionClip.xy /= positionClip.w;
|
|
|
|
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
|
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
|
|
if ( positionClip.z < -1 || positionClip.z >= 1 ) return 0.0;
|
|
|
|
const float eyeDepthScale = 1.0;
|
|
const float sampledDepthScale = light.view[1][1]; // light view matricies will incorporate scaling factors for some retarded reason, so we need to rescale it by grabbing from here, hopefully it remains coherent between all light matrices to ever exist in engine
|
|
|
|
const float bias = light.depthBias;
|
|
const float eyeDepth = abs(positionClip.z / positionClip.w) * eyeDepthScale;
|
|
|
|
const vec3 sampleOffsetDirections[20] = {
|
|
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
|
|
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
|
|
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
|
|
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
|
|
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
|
|
};
|
|
|
|
float sampled = 0;
|
|
const int samples = int(SHADOW_SAMPLES);
|
|
// cubemap point light
|
|
if ( light.typeMap == 1 ) {
|
|
if ( samples < 1 ) {
|
|
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
|
|
} else {
|
|
for ( int i = 0; i < samples; ++i ) {
|
|
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
|
|
vec2 poisson = poissonDisk[idx] / 700.0;
|
|
vec3 P = vec3( poisson.xy, (poisson.x + poisson.y) * 0.5 );
|
|
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r * sampledDepthScale;
|
|
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
|
|
}
|
|
return factor;
|
|
}
|
|
// separated point lights
|
|
} else if ( light.typeMap == 2 ) {
|
|
const vec2 uv = positionClip.xy * 0.5 + 0.5;
|
|
if ( samples < 1 ) {
|
|
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r * sampledDepthScale;
|
|
} else {
|
|
for ( int i = 0; i < samples; ++i ) {
|
|
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
|
|
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r * sampledDepthScale;
|
|
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
|
|
}
|
|
return factor;
|
|
}
|
|
}
|
|
return eyeDepth < sampled - bias ? 0.0 : factor;
|
|
}
|
|
#endif
|
|
float shadowFactor( const Light light, float def ) {
|
|
#if RT
|
|
return shadowFactorRT( light, def );
|
|
#endif
|
|
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
|
|
|
|
if ( !validTextureIndex(light.indexMap) )
|
|
#if VXGI
|
|
return shadowFactorVXGI( light, def );
|
|
#else
|
|
return 1.0;
|
|
#endif
|
|
|
|
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
|
|
positionClip.xyz /= positionClip.w;
|
|
|
|
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
|
|
if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0;
|
|
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0;
|
|
|
|
float factor = 1.0;
|
|
|
|
// spot light
|
|
if ( abs(light.type) == 2 || abs(light.type) == 3 ) {
|
|
const float dist = length( positionClip.xy );
|
|
if ( dist > 0.5 ) return def; //0.0;
|
|
|
|
// spot light with attenuation
|
|
if ( abs(light.type) == 3 ) {
|
|
factor = 1.0 - (pow(dist * 2,2.0));
|
|
}
|
|
}
|
|
|
|
const vec2 uv = positionClip.xy * 0.5 + 0.5;
|
|
const float bias = light.depthBias;
|
|
const float eyeDepth = positionClip.z;
|
|
const int samples = int(SHADOW_SAMPLES);
|
|
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.indexMap)], uv).r - bias ? 0.0 : factor;
|
|
for ( int i = 0; i < samples; ++i ) {
|
|
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
|
|
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.indexMap)], uv + poissonDisk[index] / 700.0 ).r;
|
|
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
|
|
}
|
|
return factor;
|
|
} |