@lovo/matter 0.6.0 → 1.0.0

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.
package/dist/index.d.cts CHANGED
@@ -315,23 +315,26 @@ declare function cursorRipple(p: TSLNode, center: TSLNode, opts?: CursorRippleOp
315
315
  declare const elapsedTime: ShaderNodeObject<Node>;
316
316
 
317
317
  type TSLScalar = TSLNode | number;
318
- declare function filmGrain(intensity: TSLScalar, timeOffset?: TSLScalar): ShaderNodeObject<Node>;
318
+ declare function grain(intensity: TSLScalar, timeOffset?: TSLScalar): ShaderNodeObject<Node>;
319
319
 
320
320
  /**
321
- * Add sub-LSB dither to break up 8-bit quantization banding (most visible on
322
- * wide-gamut/P3 output, where the same 256 levels span a wider gamut).
323
- *
324
- * `coord` is a per-pixel coordinate (pass `uv()`); `amount` is the noise
325
- * magnitude in the color's units (default ~1/255, roughly one 8-bit step). Uses a
326
- * triangular PDF (difference of two hashes) for flatter, less "gritty" noise than
327
- * uniform white noise.
328
- *
329
- * SPIKE NOTE: applied here in linear-sRGB working space (before the renderer's
330
- * output transfer), so the effective dither is uneven across tones (over-dithers
331
- * shadows, under-dithers highlights). The correct home is a final output pass
332
- * after color-space conversion; this is good enough to evaluate the banding fix.
321
+ * Add a sub-LSB ordered dither to break up 8-bit quantization banding (most
322
+ * visible on smooth gradients and on wide-gamut/P3 output, where the same 256
323
+ * levels span a wider gamut so each step is a coarser perceptual jump).
324
+ *
325
+ * `amount` is the noise magnitude in the color's units (default ~1/255, roughly
326
+ * one 8-bit step). The dither is an ordered Bayer 8x8 pattern keyed on the
327
+ * per-pixel `screenCoordinate`, so the grain is a crisp one device-pixel cell
328
+ * regardless of geometry or zoom, and is deterministic (no temporal shimmer —
329
+ * important for static scenes).
330
+ *
331
+ * For correctness the dither belongs in display-encoded space, immediately
332
+ * before 8-bit quantization. In a Matter-managed scene that placement is handled
333
+ * for you (`ShaderScene` applies it as a final output stage after the color
334
+ * transfer). This primitive is the entry point for Mode 2 (your own r3f canvas),
335
+ * where you apply it to your shader's output yourself.
333
336
  */
334
- declare function dither(color: TSLNode, coord: TSLNode, amount?: number): ShaderNodeObject<Node>;
337
+ declare function dither(color: TSLNode, amount?: number): ShaderNodeObject<Node>;
335
338
 
336
339
  type ReducedMotionPolicy = 'auto' | 'off' | 'slow' | 'paused';
337
340
  /**
@@ -453,4 +456,4 @@ declare class FrameScheduler {
453
456
  private readonly frame;
454
457
  }
455
458
 
456
- export { type ColorRampStop, type ColorSpace, type CreateRendererOptions, CursorInput, type CursorInputOptions, type CursorRippleOptions, type FractalNoiseOptions, FrameScheduler, type GpuBackend, type GpuRenderer, type HueInterpolation, type IntersectionWatcher, type OutputGamut, type ReducedMotionPolicy, type ReducedMotionWatcher, type SchedulerClient, type SchedulerTick, type TSLNode, type Vector2, type VisibilityWatcher, colorRamp, createIntersectionWatcher, createReducedMotionWatcher, createRenderer, createVisibilityWatcher, cursorRipple, displace, dither, elapsedTime, filmGrain, fractalNoise, getReducedMotionPolicy, getReducedMotionTimeScale, mixColor, oklabToLinearSrgb, oklchToLinearSrgb, parseColorString, quantize, setReducedMotionPolicy, signedDistanceFieldCircle, simplexNoise, srgbChannelToLinear, voronoi };
459
+ export { type ColorRampStop, type ColorSpace, type CreateRendererOptions, CursorInput, type CursorInputOptions, type CursorRippleOptions, type FractalNoiseOptions, FrameScheduler, type GpuBackend, type GpuRenderer, type HueInterpolation, type IntersectionWatcher, type OutputGamut, type ReducedMotionPolicy, type ReducedMotionWatcher, type SchedulerClient, type SchedulerTick, type TSLNode, type Vector2, type VisibilityWatcher, colorRamp, createIntersectionWatcher, createReducedMotionWatcher, createRenderer, createVisibilityWatcher, cursorRipple, displace, dither, elapsedTime, fractalNoise, getReducedMotionPolicy, getReducedMotionTimeScale, grain, mixColor, oklabToLinearSrgb, oklchToLinearSrgb, parseColorString, quantize, setReducedMotionPolicy, signedDistanceFieldCircle, simplexNoise, srgbChannelToLinear, voronoi };
package/dist/index.d.ts CHANGED
@@ -315,23 +315,26 @@ declare function cursorRipple(p: TSLNode, center: TSLNode, opts?: CursorRippleOp
315
315
  declare const elapsedTime: ShaderNodeObject<Node>;
316
316
 
317
317
  type TSLScalar = TSLNode | number;
318
- declare function filmGrain(intensity: TSLScalar, timeOffset?: TSLScalar): ShaderNodeObject<Node>;
318
+ declare function grain(intensity: TSLScalar, timeOffset?: TSLScalar): ShaderNodeObject<Node>;
319
319
 
320
320
  /**
321
- * Add sub-LSB dither to break up 8-bit quantization banding (most visible on
322
- * wide-gamut/P3 output, where the same 256 levels span a wider gamut).
323
- *
324
- * `coord` is a per-pixel coordinate (pass `uv()`); `amount` is the noise
325
- * magnitude in the color's units (default ~1/255, roughly one 8-bit step). Uses a
326
- * triangular PDF (difference of two hashes) for flatter, less "gritty" noise than
327
- * uniform white noise.
328
- *
329
- * SPIKE NOTE: applied here in linear-sRGB working space (before the renderer's
330
- * output transfer), so the effective dither is uneven across tones (over-dithers
331
- * shadows, under-dithers highlights). The correct home is a final output pass
332
- * after color-space conversion; this is good enough to evaluate the banding fix.
321
+ * Add a sub-LSB ordered dither to break up 8-bit quantization banding (most
322
+ * visible on smooth gradients and on wide-gamut/P3 output, where the same 256
323
+ * levels span a wider gamut so each step is a coarser perceptual jump).
324
+ *
325
+ * `amount` is the noise magnitude in the color's units (default ~1/255, roughly
326
+ * one 8-bit step). The dither is an ordered Bayer 8x8 pattern keyed on the
327
+ * per-pixel `screenCoordinate`, so the grain is a crisp one device-pixel cell
328
+ * regardless of geometry or zoom, and is deterministic (no temporal shimmer —
329
+ * important for static scenes).
330
+ *
331
+ * For correctness the dither belongs in display-encoded space, immediately
332
+ * before 8-bit quantization. In a Matter-managed scene that placement is handled
333
+ * for you (`ShaderScene` applies it as a final output stage after the color
334
+ * transfer). This primitive is the entry point for Mode 2 (your own r3f canvas),
335
+ * where you apply it to your shader's output yourself.
333
336
  */
334
- declare function dither(color: TSLNode, coord: TSLNode, amount?: number): ShaderNodeObject<Node>;
337
+ declare function dither(color: TSLNode, amount?: number): ShaderNodeObject<Node>;
335
338
 
336
339
  type ReducedMotionPolicy = 'auto' | 'off' | 'slow' | 'paused';
337
340
  /**
@@ -453,4 +456,4 @@ declare class FrameScheduler {
453
456
  private readonly frame;
454
457
  }
455
458
 
456
- export { type ColorRampStop, type ColorSpace, type CreateRendererOptions, CursorInput, type CursorInputOptions, type CursorRippleOptions, type FractalNoiseOptions, FrameScheduler, type GpuBackend, type GpuRenderer, type HueInterpolation, type IntersectionWatcher, type OutputGamut, type ReducedMotionPolicy, type ReducedMotionWatcher, type SchedulerClient, type SchedulerTick, type TSLNode, type Vector2, type VisibilityWatcher, colorRamp, createIntersectionWatcher, createReducedMotionWatcher, createRenderer, createVisibilityWatcher, cursorRipple, displace, dither, elapsedTime, filmGrain, fractalNoise, getReducedMotionPolicy, getReducedMotionTimeScale, mixColor, oklabToLinearSrgb, oklchToLinearSrgb, parseColorString, quantize, setReducedMotionPolicy, signedDistanceFieldCircle, simplexNoise, srgbChannelToLinear, voronoi };
459
+ export { type ColorRampStop, type ColorSpace, type CreateRendererOptions, CursorInput, type CursorInputOptions, type CursorRippleOptions, type FractalNoiseOptions, FrameScheduler, type GpuBackend, type GpuRenderer, type HueInterpolation, type IntersectionWatcher, type OutputGamut, type ReducedMotionPolicy, type ReducedMotionWatcher, type SchedulerClient, type SchedulerTick, type TSLNode, type Vector2, type VisibilityWatcher, colorRamp, createIntersectionWatcher, createReducedMotionWatcher, createRenderer, createVisibilityWatcher, cursorRipple, displace, dither, elapsedTime, fractalNoise, getReducedMotionPolicy, getReducedMotionTimeScale, grain, mixColor, oklabToLinearSrgb, oklchToLinearSrgb, parseColorString, quantize, setReducedMotionPolicy, signedDistanceFieldCircle, simplexNoise, srgbChannelToLinear, voronoi };
package/dist/index.js CHANGED
@@ -674,25 +674,33 @@ function cursorRipple(p, center, opts = {}) {
674
674
  return wave.mul(amplitude).mul(decay);
675
675
  }
676
676
 
677
- // src/primitives/film-grain/film-grain.ts
678
- import { hash, mul as mul2, screenCoordinate } from "three/tsl";
679
- function filmGrain(intensity, timeOffset = 0) {
677
+ // src/primitives/grain/grain.ts
678
+ import { float, hash, screenCoordinate } from "three/tsl";
679
+ function grain(intensity, timeOffset = 0) {
680
680
  const pixel = screenCoordinate.xy.floor();
681
- const seed = pixel.x.toUint().mul(1973).add(pixel.y.toUint().mul(9277)).add(mul2(timeOffset, 26699).toUint());
681
+ const column = pixel.x.toUint();
682
+ const row = pixel.y.toUint();
683
+ const frameHash = hash(float(timeOffset)).mul(16777215).toUint();
684
+ const rowHash = hash(row.add(frameHash)).mul(16777215).toUint();
685
+ const seed = column.add(rowHash);
682
686
  return hash(seed).sub(0.5).mul(intensity);
683
687
  }
684
688
 
685
689
  // src/primitives/dither/dither.ts
686
- import { dot, fract as fract3, sin as sin4, vec2 as vec23, vec3 as vec39 } from "three/tsl";
687
- function hash21(coord) {
688
- return fract3(sin4(dot(coord, vec23(12.9898, 78.233))).mul(43758.5453));
690
+ import { floor, fract as fract3, screenCoordinate as screenCoordinate2, vec2 as vec23, vec3 as vec39, vec4 as vec43 } from "three/tsl";
691
+ function bayer2(coord) {
692
+ const cell = floor(coord);
693
+ return fract3(cell.x.mul(0.5).add(cell.y.mul(cell.y).mul(0.75)));
689
694
  }
690
- function dither(color, coord, amount = 1 / 255) {
691
- const pixelCoord = vec23(coord);
692
- const firstHash = hash21(pixelCoord);
693
- const secondHash = hash21(pixelCoord.add(vec23(0.5, 0.5)));
694
- const triangularNoise = firstHash.sub(secondHash).mul(0.5);
695
- return vec39(color).add(triangularNoise.mul(amount));
695
+ function bayer4(coord) {
696
+ return bayer2(coord.mul(0.5)).mul(0.25).add(bayer2(coord));
697
+ }
698
+ function bayer8(coord) {
699
+ return bayer4(coord.mul(0.5)).mul(0.25).add(bayer2(coord));
700
+ }
701
+ function dither(color, amount = 1 / 255) {
702
+ const threshold = bayer8(vec23(screenCoordinate2.xy)).sub(0.5);
703
+ return vec43(vec39(color).add(threshold.mul(amount)), vec43(color).a);
696
704
  }
697
705
 
698
706
  // src/runtime/visibility/visibility.ts
@@ -773,7 +781,7 @@ var FrameScheduler = class {
773
781
  // Reference-counted idle voting. The scheduler is idle only when at least
774
782
  // one component has voted idle AND no component has voted animated. This
775
783
  // prevents a static component (e.g. LinearGradient speed=0) from halting
776
- // the loop while an animated overlay (e.g. FilmGrain) is still running.
784
+ // the loop while an animated overlay (e.g. Grain) is still running.
777
785
  idleVotes = 0;
778
786
  animatedVotes = 0;
779
787
  /** True when all participating components prefer idle and none need animation. */
@@ -907,10 +915,10 @@ export {
907
915
  displace,
908
916
  dither,
909
917
  elapsedTime,
910
- filmGrain,
911
918
  fractalNoise,
912
919
  getReducedMotionPolicy,
913
920
  getReducedMotionTimeScale,
921
+ grain,
914
922
  mixColor,
915
923
  oklabToLinearSrgb,
916
924
  oklchToLinearSrgb,