angular-three-soba 4.0.2 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -243,7 +243,7 @@ function getVersion() {
243
243
  return parseInt(REVISION.replace(/\D+/g, ''));
244
244
  }
245
245
 
246
- const defaultOptions$1 = {
246
+ const defaultOptions$2 = {
247
247
  polygonOffsetFactor: -10,
248
248
  debug: false,
249
249
  depthTest: false,
@@ -285,7 +285,7 @@ class NgtsDecal {
285
285
  /**
286
286
  * Decal configuration options including position, scale, rotation, and material properties.
287
287
  */
288
- this.options = input(defaultOptions$1, { ...(ngDevMode ? { debugName: "options" } : {}), transform: mergeInputs(defaultOptions$1) });
288
+ this.options = input(defaultOptions$2, { ...(ngDevMode ? { debugName: "options" } : {}), transform: mergeInputs(defaultOptions$2) });
289
289
  this.parameters = omit(this.options, [
290
290
  'debug',
291
291
  'map',
@@ -1632,7 +1632,7 @@ function surfaceSampler(mesh, { count, transform, weight, instancedMesh, } = {})
1632
1632
  return new THREE.InstancedBufferAttribute(initialBufferAttribute.array, initialBufferAttribute.itemSize).copy(initialBufferAttribute);
1633
1633
  });
1634
1634
  }
1635
- const defaultOptions = {
1635
+ const defaultOptions$1 = {
1636
1636
  count: 16,
1637
1637
  };
1638
1638
  /**
@@ -1677,7 +1677,7 @@ class NgtsSampler {
1677
1677
  /**
1678
1678
  * Sampler configuration including count, weight attribute, and transform function.
1679
1679
  */
1680
- this.options = input(defaultOptions, { ...(ngDevMode ? { debugName: "options" } : {}), transform: mergeInputs(defaultOptions) });
1680
+ this.options = input(defaultOptions$1, { ...(ngDevMode ? { debugName: "options" } : {}), transform: mergeInputs(defaultOptions$1) });
1681
1681
  this.parameters = omit(this.options, ['weight', 'transform', 'count']);
1682
1682
  this.groupRef = viewChild.required('group');
1683
1683
  this.count = pick(this.options, 'count');
@@ -1796,9 +1796,180 @@ function calculateScaleFactor(point3, radiusPx, camera, size) {
1796
1796
  return scale;
1797
1797
  }
1798
1798
 
1799
+ /*
1800
+ * Integration and compilation: @N8Programs
1801
+ * Inspired by:
1802
+ * https://github.com/mrdoob/three.js/blob/dev/examples/webgl_shadowmap_pcss.html
1803
+ * https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-17-efficient-soft-edged-shadows-using
1804
+ * https://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf
1805
+ * https://github.com/mrdoob/three.js/blob/master/examples/webgl_shadowmap_pcss.html [spidersharma03]
1806
+ * https://spline.design/
1807
+ * Concept:
1808
+ * https://www.gamedev.net/tutorials/programming/graphics/contact-hardening-soft-shadows-made-fast-r4906/
1809
+ * Vogel Disk Implementation:
1810
+ * https://www.shadertoy.com/view/4l3yRM [ashalah]
1811
+ * High-Frequency Noise Implementation:
1812
+ * https://www.shadertoy.com/view/tt3fDH [spawner64]
1813
+ */
1814
+ const defaultOptions = {
1815
+ size: 25,
1816
+ samples: 10,
1817
+ focus: 0,
1818
+ };
1819
+ function pcss(options) {
1820
+ const { focus, size, samples } = options;
1821
+ return `
1822
+ #define PENUMBRA_FILTER_SIZE float(${size})
1823
+ #define RGB_NOISE_FUNCTION(uv) (randRGB(uv))
1824
+ vec3 randRGB(vec2 uv) {
1825
+ return vec3(
1826
+ fract(sin(dot(uv, vec2(12.75613, 38.12123))) * 13234.76575),
1827
+ fract(sin(dot(uv, vec2(19.45531, 58.46547))) * 43678.23431),
1828
+ fract(sin(dot(uv, vec2(23.67817, 78.23121))) * 93567.23423)
1829
+ );
1830
+ }
1831
+
1832
+ vec3 lowPassRandRGB(vec2 uv) {
1833
+ // 3x3 convolution (average)
1834
+ // can be implemented as separable with an extra buffer for a total of 6 samples instead of 9
1835
+ vec3 result = vec3(0);
1836
+ result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, -1.0));
1837
+ result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, 0.0));
1838
+ result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, +1.0));
1839
+ result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, -1.0));
1840
+ result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, 0.0));
1841
+ result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, +1.0));
1842
+ result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, -1.0));
1843
+ result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, 0.0));
1844
+ result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, +1.0));
1845
+ result *= 0.111111111; // 1.0 / 9.0
1846
+ return result;
1847
+ }
1848
+ vec3 highPassRandRGB(vec2 uv) {
1849
+ // by subtracting the low-pass signal from the original signal, we're being left with the high-pass signal
1850
+ // hp(x) = x - lp(x)
1851
+ return RGB_NOISE_FUNCTION(uv) - lowPassRandRGB(uv) + 0.5;
1852
+ }
1853
+
1854
+
1855
+ vec2 vogelDiskSample(int sampleIndex, int sampleCount, float angle) {
1856
+ const float goldenAngle = 2.399963f; // radians
1857
+ float r = sqrt(float(sampleIndex) + 0.5f) / sqrt(float(sampleCount));
1858
+ float theta = float(sampleIndex) * goldenAngle + angle;
1859
+ float sine = sin(theta);
1860
+ float cosine = cos(theta);
1861
+ return vec2(cosine, sine) * r;
1862
+ }
1863
+ float penumbraSize( const in float zReceiver, const in float zBlocker ) { // Parallel plane estimation
1864
+ return (zReceiver - zBlocker) / zBlocker;
1865
+ }
1866
+ float findBlocker(sampler2D shadowMap, vec2 uv, float compare, float angle) {
1867
+ float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
1868
+ float blockerDepthSum = float(${focus});
1869
+ float blockers = 0.0;
1870
+
1871
+ int j = 0;
1872
+ vec2 offset = vec2(0.);
1873
+ float depth = 0.;
1874
+
1875
+ #pragma unroll_loop_start
1876
+ for(int i = 0; i < ${samples}; i ++) {
1877
+ offset = (vogelDiskSample(j, ${samples}, angle) * texelSize) * 2.0 * PENUMBRA_FILTER_SIZE;
1878
+ depth = unpackRGBAToDepth( texture2D( shadowMap, uv + offset));
1879
+ if (depth < compare) {
1880
+ blockerDepthSum += depth;
1881
+ blockers++;
1882
+ }
1883
+ j++;
1884
+ }
1885
+ #pragma unroll_loop_end
1886
+
1887
+ if (blockers > 0.0) {
1888
+ return blockerDepthSum / blockers;
1889
+ }
1890
+ return -1.0;
1891
+ }
1892
+
1893
+
1894
+ float vogelFilter(sampler2D shadowMap, vec2 uv, float zReceiver, float filterRadius, float angle) {
1895
+ float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
1896
+ float shadow = 0.0f;
1897
+ int j = 0;
1898
+ vec2 vogelSample = vec2(0.0);
1899
+ vec2 offset = vec2(0.0);
1900
+ #pragma unroll_loop_start
1901
+ for (int i = 0; i < ${samples}; i++) {
1902
+ vogelSample = vogelDiskSample(j, ${samples}, angle) * texelSize;
1903
+ offset = vogelSample * (1.0 + filterRadius * float(${size}));
1904
+ shadow += step( zReceiver, unpackRGBAToDepth( texture2D( shadowMap, uv + offset ) ) );
1905
+ j++;
1906
+ }
1907
+ #pragma unroll_loop_end
1908
+ return shadow * 1.0 / ${samples}.0;
1909
+ }
1910
+
1911
+ float PCSS (sampler2D shadowMap, vec4 coords) {
1912
+ vec2 uv = coords.xy;
1913
+ float zReceiver = coords.z; // Assumed to be eye-space z in this code
1914
+ float angle = highPassRandRGB(gl_FragCoord.xy).r * PI2;
1915
+ float avgBlockerDepth = findBlocker(shadowMap, uv, zReceiver, angle);
1916
+ if (avgBlockerDepth == -1.0) {
1917
+ return 1.0;
1918
+ }
1919
+ float penumbraRatio = penumbraSize(zReceiver, avgBlockerDepth);
1920
+ return vogelFilter(shadowMap, uv, zReceiver, 1.25 * penumbraRatio, angle);
1921
+ }`;
1922
+ }
1923
+ function reset(gl, scene, camera) {
1924
+ scene.traverse((object) => {
1925
+ if (object.material) {
1926
+ gl.properties.remove(object.material);
1927
+ object.material.dispose?.();
1928
+ }
1929
+ });
1930
+ gl.info.programs.length = 0;
1931
+ gl.compile(scene, camera);
1932
+ }
1933
+ /**
1934
+ * A directive that injects Percentage-Closer Soft Shadows (PCSS) into the scene.
1935
+ *
1936
+ * PCSS produces contact-hardening soft shadows where shadows are sharper near the
1937
+ * contact point and softer further away, creating more realistic shadow effects.
1938
+ *
1939
+ * @example
1940
+ * ```html
1941
+ * <ngts-soft-shadows [options]="{ size: 25, samples: 10, focus: 0 }" />
1942
+ * ```
1943
+ */
1944
+ class NgtsSoftShadows {
1945
+ constructor() {
1946
+ this.options = input(defaultOptions, { ...(ngDevMode ? { debugName: "options" } : {}), transform: mergeInputs(defaultOptions) });
1947
+ const store = injectStore();
1948
+ effect((onCleanup) => {
1949
+ const { gl, scene, camera } = store.snapshot;
1950
+ const options = this.options();
1951
+ const original = THREE.ShaderChunk.shadowmap_pars_fragment;
1952
+ THREE.ShaderChunk.shadowmap_pars_fragment = THREE.ShaderChunk.shadowmap_pars_fragment
1953
+ .replace('#ifdef USE_SHADOWMAP', '#ifdef USE_SHADOWMAP\n' + pcss(options))
1954
+ .replace('#if defined( SHADOWMAP_TYPE_PCF )', '\nreturn PCSS(shadowMap, shadowCoord);\n#if defined( SHADOWMAP_TYPE_PCF )');
1955
+ reset(gl, scene, camera);
1956
+ onCleanup(() => {
1957
+ THREE.ShaderChunk.shadowmap_pars_fragment = original;
1958
+ reset(gl, scene, camera);
1959
+ });
1960
+ });
1961
+ }
1962
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgtsSoftShadows, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1963
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: NgtsSoftShadows, isStandalone: true, selector: "ngts-soft-shadows", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
1964
+ }
1965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgtsSoftShadows, decorators: [{
1966
+ type: Directive,
1967
+ args: [{ selector: 'ngts-soft-shadows' }]
1968
+ }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }] } });
1969
+
1799
1970
  /**
1800
1971
  * Generated bundle index. Do not edit.
1801
1972
  */
1802
1973
 
1803
- export { NgtsBakeShadows, NgtsComputedAttribute, NgtsDecal, NgtsFBO, NgtsHTML, NgtsHTMLContent, NgtsHTMLImpl, NgtsIntersect, NgtsPreload, NgtsSampler, animations, calculateScaleFactor, depthBuffer, fbo, getVersion, injectAnimations, injectDepthBuffer, injectFBO, injectIntersect, intersect, setUpdateRange, surfaceSampler };
1974
+ export { NgtsBakeShadows, NgtsComputedAttribute, NgtsDecal, NgtsFBO, NgtsHTML, NgtsHTMLContent, NgtsHTMLImpl, NgtsIntersect, NgtsPreload, NgtsSampler, NgtsSoftShadows, animations, calculateScaleFactor, depthBuffer, fbo, getVersion, injectAnimations, injectDepthBuffer, injectFBO, injectIntersect, intersect, setUpdateRange, surfaceSampler };
1804
1975
  //# sourceMappingURL=angular-three-soba-misc.mjs.map