UNPKG

gpu-curtains

Version:

gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.

66 lines (53 loc) 2.29 kB
//#region src/core/shaders/chunks/fragment/head/get-PCF-base-shadow-contribution.ts /** Helper chunk to compute the shadow visibility of a fragment using `shadowCoords`, a 2D `depthTexture` and shadow properties using PCF. Returns `1` when fully visible and `0` when fully shadowed. */ const getPCFBaseShadowContribution = ` // Interleaved Gradient Noise for randomizing sampling patterns fn interleavedGradientNoise(position: vec2f) -> f32 { return fract(52.9829189 * fract(dot(position, vec2(0.06711056, 0.00583715)))); } // Vogel disk sampling for uniform circular distribution fn vogelDiskSample(sampleIndex: i32, samplesCount: i32, phi: f32) -> vec2f { let goldenAngle: f32 = 2.399963229728653; let r: f32 = sqrt((f32(sampleIndex) + 0.5) / f32(samplesCount)); let theta: f32 = f32(sampleIndex) * goldenAngle + phi; return vec2(cos(theta), sin(theta)) * r; } fn getPCFBaseShadowContribution( shadowCoords: vec3f, fragmentPosition: vec2f, pcfSamples: i32, shadowRadius: f32, bias: f32, intensity: f32, depthTexture: texture_depth_2d ) -> f32 { let inFrustum: bool = shadowCoords.x >= 0.0 && shadowCoords.x <= 1.0 && shadowCoords.y >= 0.0 && shadowCoords.y <= 1.0; let frustumTest: bool = inFrustum && shadowCoords.z <= 1.0; if(!frustumTest) { return 1.0; } var visibility = 0.0; // Percentage-closer filtering. Sample texels in the region // to smooth the result. let size: vec2f = vec2f(textureDimensions(depthTexture).xy); let texelSize: vec2f = 1.0 / size; // Hardware PCF with LinearFilter gives us 4-tap filtering per sample // 5 samples using Vogel disk + IGN = effectively 20 filtered taps with better distribution let radius: f32 = shadowRadius * texelSize.x; // Use IGN to rotate sampling pattern per pixel let phi: f32 = interleavedGradientNoise(fragmentPosition.xy) * PI2; for(var i: i32 = 0; i < pcfSamples; i++) { let offset: vec2f = vogelDiskSample(i, pcfSamples, phi) * radius; visibility += textureSampleCompareLevel( depthTexture, depthComparisonSampler, shadowCoords.xy + offset, shadowCoords.z - bias ); } visibility /= f32(pcfSamples); return mix(1.0, visibility, saturate(intensity)); } `; //#endregion export { getPCFBaseShadowContribution };