|
@@ -0,0 +1,68 @@
|
|
|
+export default /* glsl */`
|
|
|
+#ifdef USE_ALPHAHASH
|
|
|
+
|
|
|
+ /**
|
|
|
+ * See: https://casual-effects.com/research/Wyman2017Hashed/index.html
|
|
|
+ */
|
|
|
+
|
|
|
+ const float ALPHA_HASH_SCALE = 0.05; // Derived from trials only, and may be changed.
|
|
|
+
|
|
|
+ float hash2D( vec2 value ) {
|
|
|
+
|
|
|
+ return fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ float hash3D( vec3 value ) {
|
|
|
+
|
|
|
+ return hash2D( vec2( hash2D( value.xy ), value.z ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ float getAlphaHashThreshold( vec3 position ) {
|
|
|
+
|
|
|
+ // Find the discretized derivatives of our coordinates
|
|
|
+ float maxDeriv = max(
|
|
|
+ length( dFdx( position.xyz ) ),
|
|
|
+ length( dFdy( position.xyz ) )
|
|
|
+ );
|
|
|
+ float pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );
|
|
|
+
|
|
|
+ // Find two nearest log-discretized noise scales
|
|
|
+ vec2 pixScales = vec2(
|
|
|
+ exp2( floor( log2( pixScale ) ) ),
|
|
|
+ exp2( ceil( log2( pixScale ) ) )
|
|
|
+ );
|
|
|
+
|
|
|
+ // Compute alpha thresholds at our two noise scales
|
|
|
+ vec2 alpha = vec2(
|
|
|
+ hash3D( floor( pixScales.x * position.xyz ) ),
|
|
|
+ hash3D( floor( pixScales.y * position.xyz ) )
|
|
|
+ );
|
|
|
+
|
|
|
+ // Factor to interpolate lerp with
|
|
|
+ float lerpFactor = fract( log2( pixScale ) );
|
|
|
+
|
|
|
+ // Interpolate alpha threshold from noise at two scales
|
|
|
+ float x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;
|
|
|
+
|
|
|
+ // Pass into CDF to compute uniformly distrib threshold
|
|
|
+ float a = min( lerpFactor, 1.0 - lerpFactor );
|
|
|
+ vec3 cases = vec3(
|
|
|
+ x * x / ( 2.0 * a * ( 1.0 - a ) ),
|
|
|
+ ( x - 0.5 * a ) / ( 1.0 - a ),
|
|
|
+ 1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )
|
|
|
+ );
|
|
|
+
|
|
|
+ // Find our final, uniformly distributed alpha threshold (ατ)
|
|
|
+ float threshold = ( x < ( 1.0 - a ) )
|
|
|
+ ? ( ( x < a ) ? cases.x : cases.y )
|
|
|
+ : cases.z;
|
|
|
+
|
|
|
+ // Avoids ατ == 0. Could also do ατ =1-ατ
|
|
|
+ return clamp( threshold , 1.0e-6, 1.0 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+#endif
|
|
|
+`;
|