234 lines
6.2 KiB
Plaintext
234 lines
6.2 KiB
Plaintext
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Author: Kaj Dijksta
|
||
|
|
*/
|
||
|
|
|
||
|
|
attribute vec3 position;
|
||
|
|
attribute vec2 uv;
|
||
|
|
|
||
|
|
uniform mat4 viewProjection;
|
||
|
|
|
||
|
|
varying vec2 v_textureCoord;
|
||
|
|
|
||
|
|
void main(void) {
|
||
|
|
|
||
|
|
v_textureCoord = uv;
|
||
|
|
gl_Position = viewProjection * vec4(position, 1.0);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// #keplerEngine - Split
|
||
|
|
|
||
|
|
|
||
|
|
precision highp float;
|
||
|
|
|
||
|
|
uniform sampler2D positionSampler;
|
||
|
|
uniform sampler2D shadowDepthSampler;
|
||
|
|
uniform sampler2D shadowNoiseSampler;
|
||
|
|
uniform sampler2D ambientOcclusionSampler;
|
||
|
|
|
||
|
|
uniform float bias;
|
||
|
|
uniform float minVariance;
|
||
|
|
|
||
|
|
uniform vec3 lightPosition;
|
||
|
|
uniform mat4 lightViewProjection;
|
||
|
|
|
||
|
|
varying vec2 v_textureCoord;
|
||
|
|
float DecodeFloatRGBA( vec4 rgba ) {
|
||
|
|
return (rgba).x;
|
||
|
|
|
||
|
|
//return dot( rgba, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0) );
|
||
|
|
}
|
||
|
|
|
||
|
|
float poissonPCFmultitap(vec4 projCoords, float shadowDepth, vec2 uv)
|
||
|
|
{
|
||
|
|
const mediump float step = 1.0 - 1.0 / 8.0;
|
||
|
|
const mediump float fScale = 0.025; // 0.025
|
||
|
|
|
||
|
|
mediump float n = 0.0;
|
||
|
|
|
||
|
|
mediump vec3 directions[8];
|
||
|
|
float vSampleScale = 1.0 / 2048.0;
|
||
|
|
|
||
|
|
|
||
|
|
directions[0] = normalize(vec3( 1.0, 1.0, 1.0))*fScale*(n+=step);
|
||
|
|
directions[1] = normalize(vec3(-1.0,-1.0,-1.0))*fScale*(n+=step);
|
||
|
|
directions[2] = normalize(vec3(-1.0,-1.0, 1.0))*fScale*(n+=step);
|
||
|
|
directions[3] = normalize(vec3(-1.0, 1.0,-1.0))*fScale*(n+=step);
|
||
|
|
directions[4] = normalize(vec3(-1.0, 1.0 ,1.0))*fScale*(n+=step);
|
||
|
|
directions[5] = normalize(vec3( 1.0,-1.0,-1.0))*fScale*(n+=step);
|
||
|
|
directions[6] = normalize(vec3( 1.0,-1.0, 1.0))*fScale*(n+=step);
|
||
|
|
directions[7] = normalize(vec3( 1.0, 1.0,-1.0))*fScale*(n+=step);
|
||
|
|
|
||
|
|
mediump vec3 randomSample = texture2D(shadowNoiseSampler, vec2(64.0, 64.0) * uv.xy / 4.0).xyz * 2.0 - 1.0;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
float sum = 0.0;
|
||
|
|
|
||
|
|
// for( int i = 0; i < 4; i++ ) {
|
||
|
|
// vec3 sampler = reflect(directions[0], randomSample) * vSampleScale;
|
||
|
|
|
||
|
|
float pixelDepth = DecodeFloatRGBA( texture2D(shadowDepthSampler, projCoords.xy ) ) ; // + sampler.xy + sampler.z
|
||
|
|
|
||
|
|
if( pixelDepth + bias > shadowDepth) {
|
||
|
|
sum += 1.0;
|
||
|
|
} else {
|
||
|
|
sum += 0.5;
|
||
|
|
}
|
||
|
|
// }
|
||
|
|
|
||
|
|
return sum;
|
||
|
|
}
|
||
|
|
float shadow_sample(sampler2D depthMap, vec2 coord)
|
||
|
|
{
|
||
|
|
return ( texture2D(depthMap, coord.xy).x );
|
||
|
|
}
|
||
|
|
|
||
|
|
vec2 DoubleSampleRotated(sampler2D depthMap, vec4 p, vec4 rotMatr, vec4 kernel) {
|
||
|
|
|
||
|
|
vec4 rotatedOff;
|
||
|
|
|
||
|
|
rotatedOff = rotMatr.xyzw * kernel.xxww +
|
||
|
|
rotMatr.zwxy * kernel.yyzz;
|
||
|
|
|
||
|
|
vec4 fetchPos = p.xyxy + rotatedOff;// + rotatedOff
|
||
|
|
|
||
|
|
vec2 result;
|
||
|
|
|
||
|
|
result.x = shadow_sample(depthMap, fetchPos.xy);
|
||
|
|
result.y = shadow_sample(depthMap, fetchPos.zw);
|
||
|
|
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
float PCF(sampler2D depthMap, vec4 p, vec2 randDirTC, float depth)
|
||
|
|
{
|
||
|
|
|
||
|
|
vec2 kernelRadius = vec2(4.0);
|
||
|
|
|
||
|
|
vec4 irreg_kernel_2d[8];
|
||
|
|
irreg_kernel_2d[0] = vec4(-0.556641,-0.037109,-0.654297, 0.111328);
|
||
|
|
irreg_kernel_2d[1] = vec4(0.173828,0.111328,0.064453, -0.359375);
|
||
|
|
irreg_kernel_2d[2] = vec4(0.001953,0.082031,-0.060547, 0.078125);
|
||
|
|
irreg_kernel_2d[3] = vec4(0.220703,-0.359375,-0.062500, 0.001953);
|
||
|
|
irreg_kernel_2d[4] = vec4(0.242188,0.126953,-0.250000, -0.140625);
|
||
|
|
irreg_kernel_2d[5] = vec4(0.070313,-0.025391,0.148438, 0.082031);
|
||
|
|
irreg_kernel_2d[6] = vec4(-0.078125,0.013672,-0.314453, 0.013672);
|
||
|
|
irreg_kernel_2d[7] = vec4(0.117188,-0.140625,-0.199219, 0.117188);
|
||
|
|
|
||
|
|
vec2 vInvShadowMapWH = vec2(1.0 / 2048.0);
|
||
|
|
|
||
|
|
const int kernelSize = 8;
|
||
|
|
|
||
|
|
mediump float P_Z = depth; // p.z;
|
||
|
|
|
||
|
|
vec4 p0 = vec4(p.xyz, 1.0);
|
||
|
|
|
||
|
|
|
||
|
|
mediump vec2 rotScale = vec2(kernelRadius.y * 2.0);
|
||
|
|
|
||
|
|
float shadowTest = 0.0;
|
||
|
|
|
||
|
|
#define KERNEL_STEP_SIZE 2
|
||
|
|
|
||
|
|
vec2 rotSample = 2.0 * texture2D(shadowDepthSampler, randDirTC.xy).xy - 1.0;
|
||
|
|
rotSample.xy = normalize(rotSample.xy);
|
||
|
|
rotSample.xy *= (kernelRadius.xy * vInvShadowMapWH.xy);
|
||
|
|
|
||
|
|
vec4 rot = vec4(rotSample.x, -rotSample.y, rotSample.y, rotSample.x);
|
||
|
|
|
||
|
|
const int kernelOffset = 0;
|
||
|
|
|
||
|
|
for(int i=kernelOffset; i<kernelSize; i+=KERNEL_STEP_SIZE) // Loop over taps
|
||
|
|
{
|
||
|
|
|
||
|
|
mediump vec4 sampleDepth = vec4(0.0);
|
||
|
|
vec4 irr = irreg_kernel_2d[i+0];
|
||
|
|
sampleDepth.xy = DoubleSampleRotated(depthMap, p0, rot, irr);
|
||
|
|
sampleDepth.zw = DoubleSampleRotated(depthMap, p0, rot, irreg_kernel_2d[i+1]);
|
||
|
|
|
||
|
|
mediump vec4 InShadow;
|
||
|
|
InShadow.x = ( P_Z < sampleDepth.x + bias ) ? 1. : 0.0;
|
||
|
|
InShadow.y = ( P_Z < sampleDepth.y + bias ) ? 1. : 0.0;
|
||
|
|
InShadow.z = ( P_Z < sampleDepth.z + bias ) ? 1. : 0.0;
|
||
|
|
InShadow.w = ( P_Z < sampleDepth.w + bias ) ? 1. : 0.0;
|
||
|
|
|
||
|
|
|
||
|
|
const mediump float quality = 8.0; // 8 == high
|
||
|
|
const mediump float fInvSamplNum = (1.0 / quality);
|
||
|
|
|
||
|
|
shadowTest += dot(InShadow, vec4(fInvSamplNum));
|
||
|
|
}
|
||
|
|
|
||
|
|
return shadowTest;
|
||
|
|
}
|
||
|
|
float linestep(float min, float max, float value) {
|
||
|
|
return clamp((value - min) / (max - min), 0., 1.);
|
||
|
|
}
|
||
|
|
|
||
|
|
float reduceBleeding(float p_max, float amount) {
|
||
|
|
return linestep(amount, 1.0, p_max);
|
||
|
|
}
|
||
|
|
|
||
|
|
float ChebyshevUpperBound(vec2 moments, float distance) {
|
||
|
|
if (distance <= moments.x)
|
||
|
|
return 1.0;
|
||
|
|
|
||
|
|
|
||
|
|
float variance = moments.y - (moments.x*moments.x);
|
||
|
|
variance = max(variance, minVariance);
|
||
|
|
|
||
|
|
float d = distance - moments.x;
|
||
|
|
float p_max = variance / (variance + d*d);
|
||
|
|
|
||
|
|
return reduceBleeding(p_max, bias);
|
||
|
|
}
|
||
|
|
|
||
|
|
float calculateShadowOcclusion( vec3 worldPosition, vec2 uv ) {
|
||
|
|
|
||
|
|
vec4 projCoords = lightViewProjection * vec4(worldPosition, 1.0) ;
|
||
|
|
|
||
|
|
float shadowDepth = length( lightPosition - worldPosition ) ;
|
||
|
|
|
||
|
|
projCoords.xy /= projCoords.w;
|
||
|
|
projCoords = 0.5 * projCoords + 0.5;
|
||
|
|
|
||
|
|
vec4 moments = texture2D( shadowDepthSampler, projCoords.xy );
|
||
|
|
mediump vec2 randomSample = texture2D(shadowNoiseSampler, vec2(1024.) * uv / 64.0).xy * 2.0 - 1.0;
|
||
|
|
|
||
|
|
float outFrustum = 0.0;
|
||
|
|
|
||
|
|
if(projCoords.x < 0.0 || projCoords.x > 1.0) {
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(projCoords.y < 0.0 || projCoords.y > 1.0) {
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//if(projCoords.z < 1.0) {
|
||
|
|
// return 0.0;
|
||
|
|
//}
|
||
|
|
|
||
|
|
//return ChebyshevUpperBound(moments.xy, shadowDepth);
|
||
|
|
//return poissonPCFmultitap(projCoords, shadowDepth, uv);
|
||
|
|
return PCF( shadowDepthSampler, projCoords, randomSample, shadowDepth );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
|
||
|
|
vec3 position = texture2D( positionSampler, v_textureCoord ).xyz;
|
||
|
|
|
||
|
|
float shadow = calculateShadowOcclusion( position, v_textureCoord );
|
||
|
|
float ambientOcclusion = texture2D( ambientOcclusionSampler, v_textureCoord ).x;
|
||
|
|
|
||
|
|
|
||
|
|
gl_FragColor = vec4(ambientOcclusion, shadow, 0.0, 1.0);
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|