143 lines
5.5 KiB
C
143 lines
5.5 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.shadowSamples
|
|
#endif
|
|
#if VXGI
|
|
float voxelShadowFactor( 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);
|
|
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;
|
|
}
|
|
} 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 ( light.typeMap != 0 ) return omniShadowMap( light, def );
|
|
if ( !validTextureIndex(light.indexMap) )
|
|
#if VXGI
|
|
return voxelShadowFactor( 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;
|
|
} |