@react-three/postprocessing 2.12.4 → 2.13.1

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.
@@ -0,0 +1,16 @@
1
+ /// <reference types="react" />
2
+ import { Effect } from 'postprocessing';
3
+ interface IASCIIEffectProps {
4
+ characters?: string;
5
+ fontSize?: number;
6
+ cellSize?: number;
7
+ color?: string;
8
+ invert?: boolean;
9
+ }
10
+ declare class ASCIIEffect extends Effect {
11
+ constructor({ characters, fontSize, cellSize, color, invert, }?: IASCIIEffectProps);
12
+ /** Draws the characters on a Canvas and returns a texture */
13
+ createCharactersTexture(characters: string, fontSize: number): THREE.Texture;
14
+ }
15
+ export declare const ASCII: import("react").ForwardRefExoticComponent<IASCIIEffectProps & import("react").RefAttributes<ASCIIEffect>>;
16
+ export {};
@@ -1,4 +1,5 @@
1
1
  /// <reference types="react" />
2
+ import { ReactThreeFiber } from '@react-three/fiber';
2
3
  type N8AOProps = {
3
4
  aoRadius?: number;
4
5
  distanceFalloff?: number;
@@ -7,6 +8,8 @@ type N8AOProps = {
7
8
  aoSamples?: number;
8
9
  denoiseSamples?: number;
9
10
  denoiseRadius?: number;
11
+ color?: ReactThreeFiber.Color;
12
+ screenSpaceRadius?: boolean;
10
13
  };
11
14
  export declare const N8AO: import("react").ForwardRefExoticComponent<N8AOProps & import("react").RefAttributes<N8AOPostPass>>;
12
15
  export {};
package/dist/index.cjs CHANGED
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var THREE = require('three');
5
4
  var React = require('react');
5
+ var THREE = require('three');
6
6
  var fiber = require('@react-three/fiber');
7
7
  var postprocessing = require('postprocessing');
8
- var maath = require('maath');
9
8
  var threeStdlib = require('three-stdlib');
10
- var n8ao = require('n8ao');
9
+ var maath = require('maath');
11
10
  var screenSpaceReflections = require('screen-space-reflections');
11
+ var n8ao = require('n8ao');
12
12
 
13
13
  function _interopNamespaceDefault(e) {
14
14
  var n = Object.create(null);
@@ -29,6 +29,35 @@ function _interopNamespaceDefault(e) {
29
29
 
30
30
  var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
31
31
 
32
+ const selectionContext = React.createContext(null);
33
+ function Selection({ children, enabled = true }) {
34
+ const [selected, select] = React.useState([]);
35
+ const value = React.useMemo(() => ({ selected, select, enabled }), [selected, select, enabled]);
36
+ return jsxRuntime.jsx(selectionContext.Provider, { value: value, children: children });
37
+ }
38
+ function Select({ enabled = false, children, ...props }) {
39
+ const group = React.useRef(null);
40
+ const api = React.useContext(selectionContext);
41
+ React.useEffect(() => {
42
+ if (api && enabled) {
43
+ let changed = false;
44
+ const current = [];
45
+ group.current.traverse((o) => {
46
+ o.type === 'Mesh' && current.push(o);
47
+ if (api.selected.indexOf(o) === -1)
48
+ changed = true;
49
+ });
50
+ if (changed) {
51
+ api.select((state) => [...state, ...current]);
52
+ return () => {
53
+ api.select((state) => state.filter((selected) => !current.includes(selected)));
54
+ };
55
+ }
56
+ }
57
+ }, [enabled, children, api]);
58
+ return (jsxRuntime.jsx("group", { ref: group, ...props, children: children }));
59
+ }
60
+
32
61
  const EffectComposerContext = React.createContext(null);
33
62
  const EffectComposer = React.memo(React.forwardRef(({ children, camera: _camera, scene: _scene, resolutionScale, enabled = true, renderPriority = 1, autoClear = true, depthBuffer, disableNormalPass, stencilBuffer, multisampling = 8, frameBufferType = THREE.HalfFloatType, }, ref) => {
34
63
  const { gl, scene: defaultScene, camera: defaultCamera, size } = fiber.useThree();
@@ -120,6 +149,35 @@ const EffectComposer = React.memo(React.forwardRef(({ children, camera: _camera,
120
149
  return (jsxRuntime.jsx(EffectComposerContext.Provider, { value: state, children: jsxRuntime.jsx("group", { ref: group, children: children }) }));
121
150
  }));
122
151
 
152
+ const resolveRef = (ref) => typeof ref === 'object' && ref != null && 'current' in ref ? ref.current : ref;
153
+ let i = 0;
154
+ const components = new WeakMap();
155
+ const wrapEffect = (effect, defaults) =>
156
+ /* @__PURE__ */ React.forwardRef(function Effect({ blendFunction = defaults === null || defaults === void 0 ? void 0 : defaults.blendFunction, opacity = defaults === null || defaults === void 0 ? void 0 : defaults.opacity, ...props }, ref) {
157
+ let Component = components.get(effect);
158
+ if (!Component) {
159
+ const key = `@react-three/postprocessing/${effect.name}-${i++}`;
160
+ fiber.extend({ [key]: effect });
161
+ components.set(effect, (Component = key));
162
+ }
163
+ const camera = fiber.useThree((state) => state.camera);
164
+ const args = React.useMemo(() => { var _a, _b; return [...((_a = defaults === null || defaults === void 0 ? void 0 : defaults.args) !== null && _a !== void 0 ? _a : []), ...((_b = props.args) !== null && _b !== void 0 ? _b : [{ ...defaults, ...props }])]; },
165
+ // eslint-disable-next-line react-hooks/exhaustive-deps
166
+ [JSON.stringify(props)]);
167
+ return (jsxRuntime.jsx(Component, { camera: camera, "blendMode-blendFunction": blendFunction, "blendMode-opacity-value": opacity, ...props, ref: ref, args: args }));
168
+ });
169
+ const useVector2 = (props, key) => {
170
+ const value = props[key];
171
+ return React.useMemo(() => {
172
+ if (typeof value === 'number')
173
+ return new THREE__namespace.Vector2(value, value);
174
+ else if (value)
175
+ return new THREE__namespace.Vector2(...value);
176
+ else
177
+ return new THREE__namespace.Vector2();
178
+ }, [value]);
179
+ };
180
+
123
181
  const DepthOfField = React.forwardRef(function DepthOfField({ target, depthTexture, ...props }, ref) {
124
182
  const invalidate = fiber.useThree((state) => state.invalidate);
125
183
  const { camera } = React.useContext(EffectComposerContext);
@@ -224,35 +282,6 @@ const Autofocus = React.forwardRef(({ target = undefined, mouse: followMouse = f
224
282
  : null, jsxRuntime.jsx(DepthOfField, { ref: dofRef, ...props, target: hitpoint })] }));
225
283
  });
226
284
 
227
- const resolveRef = (ref) => typeof ref === 'object' && ref != null && 'current' in ref ? ref.current : ref;
228
- let i = 0;
229
- const components = new WeakMap();
230
- const wrapEffect = (effect, defaults) =>
231
- /* @__PURE__ */ React.forwardRef(function Effect({ blendFunction = defaults === null || defaults === void 0 ? void 0 : defaults.blendFunction, opacity = defaults === null || defaults === void 0 ? void 0 : defaults.opacity, ...props }, ref) {
232
- let Component = components.get(effect);
233
- if (!Component) {
234
- const key = `@react-three/postprocessing/${effect.name}-${i++}`;
235
- fiber.extend({ [key]: effect });
236
- components.set(effect, (Component = key));
237
- }
238
- const camera = fiber.useThree((state) => state.camera);
239
- const args = React.useMemo(() => { var _a, _b; return [...((_a = defaults === null || defaults === void 0 ? void 0 : defaults.args) !== null && _a !== void 0 ? _a : []), ...((_b = props.args) !== null && _b !== void 0 ? _b : [{ ...defaults, ...props }])]; },
240
- // eslint-disable-next-line react-hooks/exhaustive-deps
241
- [JSON.stringify(props)]);
242
- return (jsxRuntime.jsx(Component, { camera: camera, "blendMode-blendFunction": blendFunction, "blendMode-opacity-value": opacity, ...props, ref: ref, args: args }));
243
- });
244
- const useVector2 = (props, key) => {
245
- const value = props[key];
246
- return React.useMemo(() => {
247
- if (typeof value === 'number')
248
- return new THREE__namespace.Vector2(value, value);
249
- else if (value)
250
- return new THREE__namespace.Vector2(...value);
251
- else
252
- return new THREE__namespace.Vector2();
253
- }, [value]);
254
- };
255
-
256
285
  const Bloom = wrapEffect(postprocessing.BloomEffect, {
257
286
  blendFunction: postprocessing.BlendFunction.ADD,
258
287
  });
@@ -313,35 +342,6 @@ const HueSaturation = wrapEffect(postprocessing.HueSaturationEffect);
313
342
 
314
343
  const Noise = wrapEffect(postprocessing.NoiseEffect, { blendFunction: postprocessing.BlendFunction.COLOR_DODGE });
315
344
 
316
- const selectionContext = React.createContext(null);
317
- function Selection({ children, enabled = true }) {
318
- const [selected, select] = React.useState([]);
319
- const value = React.useMemo(() => ({ selected, select, enabled }), [selected, select, enabled]);
320
- return jsxRuntime.jsx(selectionContext.Provider, { value: value, children: children });
321
- }
322
- function Select({ enabled = false, children, ...props }) {
323
- const group = React.useRef(null);
324
- const api = React.useContext(selectionContext);
325
- React.useEffect(() => {
326
- if (api && enabled) {
327
- let changed = false;
328
- const current = [];
329
- group.current.traverse((o) => {
330
- o.type === 'Mesh' && current.push(o);
331
- if (api.selected.indexOf(o) === -1)
332
- changed = true;
333
- });
334
- if (changed) {
335
- api.select((state) => [...state, ...current]);
336
- return () => {
337
- api.select((state) => state.filter((selected) => !current.includes(selected)));
338
- };
339
- }
340
- }
341
- }, [enabled, children, api]);
342
- return (jsxRuntime.jsx("group", { ref: group, ...props, children: children }));
343
- }
344
-
345
345
  const Outline = React.forwardRef(function Outline({ selection = [], selectionLayer = 10, blendFunction, patternTexture, edgeStrength, pulseSpeed, visibleEdgeColor, hiddenEdgeColor, width, height, kernelSize, blur, xRay, ...props }, forwardRef) {
346
346
  const invalidate = fiber.useThree((state) => state.invalidate);
347
347
  const { scene, camera } = React.useContext(EffectComposerContext);
@@ -509,26 +509,6 @@ const SSAO = React.forwardRef(function SSAO(props, ref) {
509
509
  return jsxRuntime.jsx("primitive", { ref: ref, object: effect, dispose: null });
510
510
  });
511
511
 
512
- const N8AO = React.forwardRef(({ quality, aoRadius = 5, aoSamples = 16, denoiseSamples = 4, denoiseRadius = 12, distanceFalloff = 1, intensity = 1, }, ref) => {
513
- const { camera, scene } = fiber.useThree();
514
- const effect = React.useMemo(() => new n8ao.N8AOPostPass(scene, camera), []);
515
- React.useLayoutEffect(() => {
516
- Object.assign(effect.configuration, {
517
- aoRadius,
518
- distanceFalloff,
519
- intensity,
520
- aoSamples,
521
- denoiseSamples,
522
- denoiseRadius,
523
- });
524
- }, [aoRadius, distanceFalloff, intensity, aoSamples, denoiseSamples, denoiseRadius]);
525
- React.useLayoutEffect(() => {
526
- if (quality)
527
- effect.setQualityMode(quality.charAt(0).toUpperCase() + quality.slice(1));
528
- }, [quality]);
529
- return jsxRuntime.jsx("primitive", { ref: ref, object: effect });
530
- });
531
-
532
512
  const SMAA = wrapEffect(postprocessing.SMAAEffect);
533
513
 
534
514
  const Texture = React.forwardRef(function Texture({ textureSrc, texture, ...props }, ref) {
@@ -645,6 +625,93 @@ class TiltShiftEffect extends postprocessing.Effect {
645
625
  }
646
626
  const TiltShift2 = wrapEffect(TiltShiftEffect, { blendFunction: postprocessing.BlendFunction.NORMAL });
647
627
 
628
+ const fragment = `
629
+ uniform sampler2D uCharacters;
630
+ uniform float uCharactersCount;
631
+ uniform float uCellSize;
632
+ uniform bool uInvert;
633
+ uniform vec3 uColor;
634
+
635
+ const vec2 SIZE = vec2(16.);
636
+
637
+ vec3 greyscale(vec3 color, float strength) {
638
+ float g = dot(color, vec3(0.299, 0.587, 0.114));
639
+ return mix(color, vec3(g), strength);
640
+ }
641
+
642
+ vec3 greyscale(vec3 color) {
643
+ return greyscale(color, 1.0);
644
+ }
645
+
646
+ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
647
+ vec2 cell = resolution / uCellSize;
648
+ vec2 grid = 1.0 / cell;
649
+ vec2 pixelizedUV = grid * (0.5 + floor(uv / grid));
650
+ vec4 pixelized = texture2D(inputBuffer, pixelizedUV);
651
+ float greyscaled = greyscale(pixelized.rgb).r;
652
+
653
+ if (uInvert) {
654
+ greyscaled = 1.0 - greyscaled;
655
+ }
656
+
657
+ float characterIndex = floor((uCharactersCount - 1.0) * greyscaled);
658
+ vec2 characterPosition = vec2(mod(characterIndex, SIZE.x), floor(characterIndex / SIZE.y));
659
+ vec2 offset = vec2(characterPosition.x, -characterPosition.y) / SIZE;
660
+ vec2 charUV = mod(uv * (cell / SIZE), 1.0 / SIZE) - vec2(0., 1.0 / SIZE) + offset;
661
+ vec4 asciiCharacter = texture2D(uCharacters, charUV);
662
+
663
+ asciiCharacter.rgb = uColor * asciiCharacter.r;
664
+ asciiCharacter.a = pixelized.a;
665
+ outputColor = asciiCharacter;
666
+ }
667
+ `;
668
+ class ASCIIEffect extends postprocessing.Effect {
669
+ constructor({ characters = ` .:,'-^=*+?!|0#X%WM@`, fontSize = 54, cellSize = 16, color = '#ffffff', invert = false, } = {}) {
670
+ const uniforms = new Map([
671
+ ['uCharacters', new THREE.Uniform(new THREE.Texture())],
672
+ ['uCellSize', new THREE.Uniform(cellSize)],
673
+ ['uCharactersCount', new THREE.Uniform(characters.length)],
674
+ ['uColor', new THREE.Uniform(new THREE.Color(color))],
675
+ ['uInvert', new THREE.Uniform(invert)],
676
+ ]);
677
+ super('ASCIIEffect', fragment, { uniforms });
678
+ const charactersTextureUniform = this.uniforms.get('uCharacters');
679
+ if (charactersTextureUniform) {
680
+ charactersTextureUniform.value = this.createCharactersTexture(characters, fontSize);
681
+ }
682
+ }
683
+ /** Draws the characters on a Canvas and returns a texture */
684
+ createCharactersTexture(characters, fontSize) {
685
+ const canvas = document.createElement('canvas');
686
+ const SIZE = 1024;
687
+ const MAX_PER_ROW = 16;
688
+ const CELL = SIZE / MAX_PER_ROW;
689
+ canvas.width = canvas.height = SIZE;
690
+ const texture = new THREE.CanvasTexture(canvas, undefined, THREE.RepeatWrapping, THREE.RepeatWrapping, THREE.NearestFilter, THREE.NearestFilter);
691
+ const context = canvas.getContext('2d');
692
+ if (!context) {
693
+ throw new Error('Context not available');
694
+ }
695
+ context.clearRect(0, 0, SIZE, SIZE);
696
+ context.font = `${fontSize}px arial`;
697
+ context.textAlign = 'center';
698
+ context.textBaseline = 'middle';
699
+ context.fillStyle = '#fff';
700
+ for (let i = 0; i < characters.length; i++) {
701
+ const char = characters[i];
702
+ const x = i % MAX_PER_ROW;
703
+ const y = Math.floor(i / MAX_PER_ROW);
704
+ context.fillText(char, x * CELL + CELL / 2, y * CELL + CELL / 2);
705
+ }
706
+ texture.needsUpdate = true;
707
+ return texture;
708
+ }
709
+ }
710
+ const ASCII = React.forwardRef(({ characters = ` .:,'-^=*+?!|0#X%WM@`, fontSize = 54, cellSize = 16, color = '#ffffff', invert = false }, fref) => {
711
+ const effect = React.useMemo(() => new ASCIIEffect({ characters, fontSize, cellSize, color, invert }), [characters, fontSize, cellSize, color, invert]);
712
+ return jsxRuntime.jsx("primitive", { ref: fref, object: effect });
713
+ });
714
+
648
715
  const SSR = React.forwardRef(function SSR({ ENABLE_BLUR = true, USE_MRT = true, ...props }, ref) {
649
716
  const { invalidate } = fiber.useThree();
650
717
  const { scene, camera } = React.useContext(EffectComposerContext);
@@ -666,6 +733,29 @@ const SSR = React.forwardRef(function SSR({ ENABLE_BLUR = true, USE_MRT = true,
666
733
  return jsxRuntime.jsx("primitive", { ref: ref, object: effect, ...props });
667
734
  });
668
735
 
736
+ const N8AO = React.forwardRef(({ screenSpaceRadius, quality, aoRadius = 5, aoSamples = 16, denoiseSamples = 4, denoiseRadius = 12, distanceFalloff = 1, intensity = 1, color, }, ref) => {
737
+ const { camera, scene } = fiber.useThree();
738
+ const effect = React.useMemo(() => new n8ao.N8AOPostPass(scene, camera), []);
739
+ React.useLayoutEffect(() => {
740
+ fiber.applyProps(effect.configuration, {
741
+ color,
742
+ aoRadius,
743
+ distanceFalloff,
744
+ intensity,
745
+ aoSamples,
746
+ denoiseSamples,
747
+ denoiseRadius,
748
+ screenSpaceRadius,
749
+ });
750
+ }, [screenSpaceRadius, color, aoRadius, distanceFalloff, intensity, aoSamples, denoiseSamples, denoiseRadius]);
751
+ React.useLayoutEffect(() => {
752
+ if (quality)
753
+ effect.setQualityMode(quality.charAt(0).toUpperCase() + quality.slice(1));
754
+ }, [quality]);
755
+ return jsxRuntime.jsx("primitive", { ref: ref, object: effect });
756
+ });
757
+
758
+ exports.ASCII = ASCII;
669
759
  exports.Autofocus = Autofocus;
670
760
  exports.Bloom = Bloom;
671
761
  exports.BrightnessContrast = BrightnessContrast;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export * from './Selection';
2
+ export * from './EffectComposer';
3
+ export * from './util';
1
4
  export * from './effects/Autofocus';
2
5
  export * from './effects/Bloom';
3
6
  export * from './effects/BrightnessContrast';
@@ -5,7 +8,7 @@ export * from './effects/ChromaticAberration';
5
8
  export * from './effects/ColorAverage';
6
9
  export * from './effects/ColorDepth';
7
10
  export * from './effects/Depth';
8
- export { DepthOfField } from './effects/DepthOfField';
11
+ export * from './effects/DepthOfField';
9
12
  export * from './effects/DotScreen';
10
13
  export * from './effects/Glitch';
11
14
  export * from './effects/GodRays';
@@ -18,7 +21,6 @@ export * from './effects/ScanlineEffect';
18
21
  export * from './effects/SelectiveBloom';
19
22
  export * from './effects/Sepia';
20
23
  export * from './effects/SSAO';
21
- export * from './effects/N8AO';
22
24
  export * from './effects/SMAA';
23
25
  export * from './effects/Texture';
24
26
  export * from './effects/ToneMapping';
@@ -27,7 +29,6 @@ export * from './effects/ShockWave';
27
29
  export * from './effects/LUT';
28
30
  export * from './effects/TiltShift';
29
31
  export * from './effects/TiltShift2';
32
+ export * from './effects/ASCII';
30
33
  export * from './effects/SSR';
31
- export * from './Selection';
32
- export * from './EffectComposer';
33
- export * from './util';
34
+ export * from './effects/N8AO';
package/dist/index.js CHANGED
@@ -1,13 +1,42 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import React, { createContext, useState, useMemo, useRef, useContext, useEffect, forwardRef, useLayoutEffect, useImperativeHandle, useCallback } from 'react';
2
3
  import * as THREE from 'three';
3
- import { HalfFloatType, Vector3, TextureLoader, sRGBEncoding, RepeatWrapping, Uniform } from 'three';
4
- import React, { createContext, forwardRef, useMemo, useEffect, useRef, useLayoutEffect, useImperativeHandle, useContext, useState, useCallback } from 'react';
5
- import { useThree, useFrame, useInstanceHandle, createPortal, extend, useLoader } from '@react-three/fiber';
4
+ import { HalfFloatType, Vector3, TextureLoader, sRGBEncoding, RepeatWrapping, Uniform, Texture as Texture$1, Color, CanvasTexture, NearestFilter } from 'three';
5
+ import { useThree, useFrame, useInstanceHandle, extend, createPortal, useLoader, applyProps } from '@react-three/fiber';
6
6
  import { EffectComposer as EffectComposer$1, RenderPass, NormalPass, DepthDownsamplingPass, Effect, EffectPass, Pass, DepthOfFieldEffect, MaskFunction, DepthPickingPass, CopyPass, BlendFunction, BloomEffect, BrightnessContrastEffect, ChromaticAberrationEffect, ColorAverageEffect, ColorDepthEffect, DepthEffect, DotScreenEffect, GlitchEffect, GlitchMode, GodRaysEffect, GridEffect, HueSaturationEffect, NoiseEffect, OutlineEffect, PixelationEffect, ScanlineEffect, SelectiveBloomEffect, SepiaEffect, SSAOEffect, SMAAEffect, TextureEffect, ToneMappingEffect, VignetteEffect, ShockWaveEffect, LUT3DEffect, TiltShiftEffect as TiltShiftEffect$1, EffectAttribute } from 'postprocessing';
7
- import { easing } from 'maath';
8
7
  import { isWebGL2Available } from 'three-stdlib';
9
- import { N8AOPostPass } from 'n8ao';
8
+ import { easing } from 'maath';
10
9
  import { SSREffect } from 'screen-space-reflections';
10
+ import { N8AOPostPass } from 'n8ao';
11
+
12
+ const selectionContext = createContext(null);
13
+ function Selection({ children, enabled = true }) {
14
+ const [selected, select] = useState([]);
15
+ const value = useMemo(() => ({ selected, select, enabled }), [selected, select, enabled]);
16
+ return jsx(selectionContext.Provider, { value: value, children: children });
17
+ }
18
+ function Select({ enabled = false, children, ...props }) {
19
+ const group = useRef(null);
20
+ const api = useContext(selectionContext);
21
+ useEffect(() => {
22
+ if (api && enabled) {
23
+ let changed = false;
24
+ const current = [];
25
+ group.current.traverse((o) => {
26
+ o.type === 'Mesh' && current.push(o);
27
+ if (api.selected.indexOf(o) === -1)
28
+ changed = true;
29
+ });
30
+ if (changed) {
31
+ api.select((state) => [...state, ...current]);
32
+ return () => {
33
+ api.select((state) => state.filter((selected) => !current.includes(selected)));
34
+ };
35
+ }
36
+ }
37
+ }, [enabled, children, api]);
38
+ return (jsx("group", { ref: group, ...props, children: children }));
39
+ }
11
40
 
12
41
  const EffectComposerContext = createContext(null);
13
42
  const EffectComposer = React.memo(forwardRef(({ children, camera: _camera, scene: _scene, resolutionScale, enabled = true, renderPriority = 1, autoClear = true, depthBuffer, disableNormalPass, stencilBuffer, multisampling = 8, frameBufferType = HalfFloatType, }, ref) => {
@@ -100,6 +129,35 @@ const EffectComposer = React.memo(forwardRef(({ children, camera: _camera, scene
100
129
  return (jsx(EffectComposerContext.Provider, { value: state, children: jsx("group", { ref: group, children: children }) }));
101
130
  }));
102
131
 
132
+ const resolveRef = (ref) => typeof ref === 'object' && ref != null && 'current' in ref ? ref.current : ref;
133
+ let i = 0;
134
+ const components = new WeakMap();
135
+ const wrapEffect = (effect, defaults) =>
136
+ /* @__PURE__ */ React.forwardRef(function Effect({ blendFunction = defaults === null || defaults === void 0 ? void 0 : defaults.blendFunction, opacity = defaults === null || defaults === void 0 ? void 0 : defaults.opacity, ...props }, ref) {
137
+ let Component = components.get(effect);
138
+ if (!Component) {
139
+ const key = `@react-three/postprocessing/${effect.name}-${i++}`;
140
+ extend({ [key]: effect });
141
+ components.set(effect, (Component = key));
142
+ }
143
+ const camera = useThree((state) => state.camera);
144
+ const args = React.useMemo(() => { var _a, _b; return [...((_a = defaults === null || defaults === void 0 ? void 0 : defaults.args) !== null && _a !== void 0 ? _a : []), ...((_b = props.args) !== null && _b !== void 0 ? _b : [{ ...defaults, ...props }])]; },
145
+ // eslint-disable-next-line react-hooks/exhaustive-deps
146
+ [JSON.stringify(props)]);
147
+ return (jsx(Component, { camera: camera, "blendMode-blendFunction": blendFunction, "blendMode-opacity-value": opacity, ...props, ref: ref, args: args }));
148
+ });
149
+ const useVector2 = (props, key) => {
150
+ const value = props[key];
151
+ return React.useMemo(() => {
152
+ if (typeof value === 'number')
153
+ return new THREE.Vector2(value, value);
154
+ else if (value)
155
+ return new THREE.Vector2(...value);
156
+ else
157
+ return new THREE.Vector2();
158
+ }, [value]);
159
+ };
160
+
103
161
  const DepthOfField = forwardRef(function DepthOfField({ target, depthTexture, ...props }, ref) {
104
162
  const invalidate = useThree((state) => state.invalidate);
105
163
  const { camera } = useContext(EffectComposerContext);
@@ -204,35 +262,6 @@ const Autofocus = forwardRef(({ target = undefined, mouse: followMouse = false,
204
262
  : null, jsx(DepthOfField, { ref: dofRef, ...props, target: hitpoint })] }));
205
263
  });
206
264
 
207
- const resolveRef = (ref) => typeof ref === 'object' && ref != null && 'current' in ref ? ref.current : ref;
208
- let i = 0;
209
- const components = new WeakMap();
210
- const wrapEffect = (effect, defaults) =>
211
- /* @__PURE__ */ React.forwardRef(function Effect({ blendFunction = defaults === null || defaults === void 0 ? void 0 : defaults.blendFunction, opacity = defaults === null || defaults === void 0 ? void 0 : defaults.opacity, ...props }, ref) {
212
- let Component = components.get(effect);
213
- if (!Component) {
214
- const key = `@react-three/postprocessing/${effect.name}-${i++}`;
215
- extend({ [key]: effect });
216
- components.set(effect, (Component = key));
217
- }
218
- const camera = useThree((state) => state.camera);
219
- const args = React.useMemo(() => { var _a, _b; return [...((_a = defaults === null || defaults === void 0 ? void 0 : defaults.args) !== null && _a !== void 0 ? _a : []), ...((_b = props.args) !== null && _b !== void 0 ? _b : [{ ...defaults, ...props }])]; },
220
- // eslint-disable-next-line react-hooks/exhaustive-deps
221
- [JSON.stringify(props)]);
222
- return (jsx(Component, { camera: camera, "blendMode-blendFunction": blendFunction, "blendMode-opacity-value": opacity, ...props, ref: ref, args: args }));
223
- });
224
- const useVector2 = (props, key) => {
225
- const value = props[key];
226
- return React.useMemo(() => {
227
- if (typeof value === 'number')
228
- return new THREE.Vector2(value, value);
229
- else if (value)
230
- return new THREE.Vector2(...value);
231
- else
232
- return new THREE.Vector2();
233
- }, [value]);
234
- };
235
-
236
265
  const Bloom = wrapEffect(BloomEffect, {
237
266
  blendFunction: BlendFunction.ADD,
238
267
  });
@@ -293,35 +322,6 @@ const HueSaturation = wrapEffect(HueSaturationEffect);
293
322
 
294
323
  const Noise = wrapEffect(NoiseEffect, { blendFunction: BlendFunction.COLOR_DODGE });
295
324
 
296
- const selectionContext = createContext(null);
297
- function Selection({ children, enabled = true }) {
298
- const [selected, select] = useState([]);
299
- const value = useMemo(() => ({ selected, select, enabled }), [selected, select, enabled]);
300
- return jsx(selectionContext.Provider, { value: value, children: children });
301
- }
302
- function Select({ enabled = false, children, ...props }) {
303
- const group = useRef(null);
304
- const api = useContext(selectionContext);
305
- useEffect(() => {
306
- if (api && enabled) {
307
- let changed = false;
308
- const current = [];
309
- group.current.traverse((o) => {
310
- o.type === 'Mesh' && current.push(o);
311
- if (api.selected.indexOf(o) === -1)
312
- changed = true;
313
- });
314
- if (changed) {
315
- api.select((state) => [...state, ...current]);
316
- return () => {
317
- api.select((state) => state.filter((selected) => !current.includes(selected)));
318
- };
319
- }
320
- }
321
- }, [enabled, children, api]);
322
- return (jsx("group", { ref: group, ...props, children: children }));
323
- }
324
-
325
325
  const Outline = forwardRef(function Outline({ selection = [], selectionLayer = 10, blendFunction, patternTexture, edgeStrength, pulseSpeed, visibleEdgeColor, hiddenEdgeColor, width, height, kernelSize, blur, xRay, ...props }, forwardRef) {
326
326
  const invalidate = useThree((state) => state.invalidate);
327
327
  const { scene, camera } = useContext(EffectComposerContext);
@@ -489,26 +489,6 @@ const SSAO = forwardRef(function SSAO(props, ref) {
489
489
  return jsx("primitive", { ref: ref, object: effect, dispose: null });
490
490
  });
491
491
 
492
- const N8AO = forwardRef(({ quality, aoRadius = 5, aoSamples = 16, denoiseSamples = 4, denoiseRadius = 12, distanceFalloff = 1, intensity = 1, }, ref) => {
493
- const { camera, scene } = useThree();
494
- const effect = useMemo(() => new N8AOPostPass(scene, camera), []);
495
- useLayoutEffect(() => {
496
- Object.assign(effect.configuration, {
497
- aoRadius,
498
- distanceFalloff,
499
- intensity,
500
- aoSamples,
501
- denoiseSamples,
502
- denoiseRadius,
503
- });
504
- }, [aoRadius, distanceFalloff, intensity, aoSamples, denoiseSamples, denoiseRadius]);
505
- useLayoutEffect(() => {
506
- if (quality)
507
- effect.setQualityMode(quality.charAt(0).toUpperCase() + quality.slice(1));
508
- }, [quality]);
509
- return jsx("primitive", { ref: ref, object: effect });
510
- });
511
-
512
492
  const SMAA = wrapEffect(SMAAEffect);
513
493
 
514
494
  const Texture = forwardRef(function Texture({ textureSrc, texture, ...props }, ref) {
@@ -625,6 +605,93 @@ class TiltShiftEffect extends Effect {
625
605
  }
626
606
  const TiltShift2 = wrapEffect(TiltShiftEffect, { blendFunction: BlendFunction.NORMAL });
627
607
 
608
+ const fragment = `
609
+ uniform sampler2D uCharacters;
610
+ uniform float uCharactersCount;
611
+ uniform float uCellSize;
612
+ uniform bool uInvert;
613
+ uniform vec3 uColor;
614
+
615
+ const vec2 SIZE = vec2(16.);
616
+
617
+ vec3 greyscale(vec3 color, float strength) {
618
+ float g = dot(color, vec3(0.299, 0.587, 0.114));
619
+ return mix(color, vec3(g), strength);
620
+ }
621
+
622
+ vec3 greyscale(vec3 color) {
623
+ return greyscale(color, 1.0);
624
+ }
625
+
626
+ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
627
+ vec2 cell = resolution / uCellSize;
628
+ vec2 grid = 1.0 / cell;
629
+ vec2 pixelizedUV = grid * (0.5 + floor(uv / grid));
630
+ vec4 pixelized = texture2D(inputBuffer, pixelizedUV);
631
+ float greyscaled = greyscale(pixelized.rgb).r;
632
+
633
+ if (uInvert) {
634
+ greyscaled = 1.0 - greyscaled;
635
+ }
636
+
637
+ float characterIndex = floor((uCharactersCount - 1.0) * greyscaled);
638
+ vec2 characterPosition = vec2(mod(characterIndex, SIZE.x), floor(characterIndex / SIZE.y));
639
+ vec2 offset = vec2(characterPosition.x, -characterPosition.y) / SIZE;
640
+ vec2 charUV = mod(uv * (cell / SIZE), 1.0 / SIZE) - vec2(0., 1.0 / SIZE) + offset;
641
+ vec4 asciiCharacter = texture2D(uCharacters, charUV);
642
+
643
+ asciiCharacter.rgb = uColor * asciiCharacter.r;
644
+ asciiCharacter.a = pixelized.a;
645
+ outputColor = asciiCharacter;
646
+ }
647
+ `;
648
+ class ASCIIEffect extends Effect {
649
+ constructor({ characters = ` .:,'-^=*+?!|0#X%WM@`, fontSize = 54, cellSize = 16, color = '#ffffff', invert = false, } = {}) {
650
+ const uniforms = new Map([
651
+ ['uCharacters', new Uniform(new Texture$1())],
652
+ ['uCellSize', new Uniform(cellSize)],
653
+ ['uCharactersCount', new Uniform(characters.length)],
654
+ ['uColor', new Uniform(new Color(color))],
655
+ ['uInvert', new Uniform(invert)],
656
+ ]);
657
+ super('ASCIIEffect', fragment, { uniforms });
658
+ const charactersTextureUniform = this.uniforms.get('uCharacters');
659
+ if (charactersTextureUniform) {
660
+ charactersTextureUniform.value = this.createCharactersTexture(characters, fontSize);
661
+ }
662
+ }
663
+ /** Draws the characters on a Canvas and returns a texture */
664
+ createCharactersTexture(characters, fontSize) {
665
+ const canvas = document.createElement('canvas');
666
+ const SIZE = 1024;
667
+ const MAX_PER_ROW = 16;
668
+ const CELL = SIZE / MAX_PER_ROW;
669
+ canvas.width = canvas.height = SIZE;
670
+ const texture = new CanvasTexture(canvas, undefined, RepeatWrapping, RepeatWrapping, NearestFilter, NearestFilter);
671
+ const context = canvas.getContext('2d');
672
+ if (!context) {
673
+ throw new Error('Context not available');
674
+ }
675
+ context.clearRect(0, 0, SIZE, SIZE);
676
+ context.font = `${fontSize}px arial`;
677
+ context.textAlign = 'center';
678
+ context.textBaseline = 'middle';
679
+ context.fillStyle = '#fff';
680
+ for (let i = 0; i < characters.length; i++) {
681
+ const char = characters[i];
682
+ const x = i % MAX_PER_ROW;
683
+ const y = Math.floor(i / MAX_PER_ROW);
684
+ context.fillText(char, x * CELL + CELL / 2, y * CELL + CELL / 2);
685
+ }
686
+ texture.needsUpdate = true;
687
+ return texture;
688
+ }
689
+ }
690
+ const ASCII = forwardRef(({ characters = ` .:,'-^=*+?!|0#X%WM@`, fontSize = 54, cellSize = 16, color = '#ffffff', invert = false }, fref) => {
691
+ const effect = useMemo(() => new ASCIIEffect({ characters, fontSize, cellSize, color, invert }), [characters, fontSize, cellSize, color, invert]);
692
+ return jsx("primitive", { ref: fref, object: effect });
693
+ });
694
+
628
695
  const SSR = forwardRef(function SSR({ ENABLE_BLUR = true, USE_MRT = true, ...props }, ref) {
629
696
  const { invalidate } = useThree();
630
697
  const { scene, camera } = useContext(EffectComposerContext);
@@ -646,4 +713,26 @@ const SSR = forwardRef(function SSR({ ENABLE_BLUR = true, USE_MRT = true, ...pro
646
713
  return jsx("primitive", { ref: ref, object: effect, ...props });
647
714
  });
648
715
 
649
- export { Autofocus, Bloom, BrightnessContrast, ChromaticAberration, ColorAverage, ColorDepth, Depth, DepthOfField, DotScreen, EffectComposer, EffectComposerContext, Glitch, GodRays, Grid, HueSaturation, LUT, N8AO, Noise, Outline, Pixelation, SMAA, SSAO, SSR, Scanline, Select, Selection, SelectiveBloom, Sepia, ShockWave, Texture, TiltShift, TiltShift2, TiltShiftEffect, ToneMapping, Vignette, resolveRef, selectionContext, useVector2, wrapEffect };
716
+ const N8AO = forwardRef(({ screenSpaceRadius, quality, aoRadius = 5, aoSamples = 16, denoiseSamples = 4, denoiseRadius = 12, distanceFalloff = 1, intensity = 1, color, }, ref) => {
717
+ const { camera, scene } = useThree();
718
+ const effect = useMemo(() => new N8AOPostPass(scene, camera), []);
719
+ useLayoutEffect(() => {
720
+ applyProps(effect.configuration, {
721
+ color,
722
+ aoRadius,
723
+ distanceFalloff,
724
+ intensity,
725
+ aoSamples,
726
+ denoiseSamples,
727
+ denoiseRadius,
728
+ screenSpaceRadius,
729
+ });
730
+ }, [screenSpaceRadius, color, aoRadius, distanceFalloff, intensity, aoSamples, denoiseSamples, denoiseRadius]);
731
+ useLayoutEffect(() => {
732
+ if (quality)
733
+ effect.setQualityMode(quality.charAt(0).toUpperCase() + quality.slice(1));
734
+ }, [quality]);
735
+ return jsx("primitive", { ref: ref, object: effect });
736
+ });
737
+
738
+ export { ASCII, Autofocus, Bloom, BrightnessContrast, ChromaticAberration, ColorAverage, ColorDepth, Depth, DepthOfField, DotScreen, EffectComposer, EffectComposerContext, Glitch, GodRays, Grid, HueSaturation, LUT, N8AO, Noise, Outline, Pixelation, SMAA, SSAO, SSR, Scanline, Select, Selection, SelectiveBloom, Sepia, ShockWave, Texture, TiltShift, TiltShift2, TiltShiftEffect, ToneMapping, Vignette, resolveRef, selectionContext, useVector2, wrapEffect };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/postprocessing",
3
- "version": "2.12.4",
3
+ "version": "2.13.1",
4
4
  "description": "postprocessing wrapper for React and @react-three/fiber",
5
5
  "keywords": [
6
6
  "postprocessing",
@@ -48,8 +48,8 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "maath": "^0.5.3",
51
- "n8ao": "^1.2.1",
52
- "postprocessing": "^6.30.2",
51
+ "n8ao": "^1.4.0",
52
+ "postprocessing": "^6.31.0",
53
53
  "screen-space-reflections": "2.5.0",
54
54
  "three-stdlib": "^2.21.10"
55
55
  },