Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 36 additions & 35 deletions src/effects/ASCII.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
// From: https://github.com/emilwidlund/ASCII
// https://twitter.com/emilwidlund/status/1652386482420609024

import { forwardRef, useMemo } from 'react'
import { CanvasTexture, Color, NearestFilter, RepeatWrapping, Texture, Uniform } from 'three'
import { Effect } from 'postprocessing'
import { Ref, useMemo } from 'react'
import { CanvasTexture, Color, NearestFilter, RepeatWrapping, Texture, Uniform } from 'three'
import { useDispose } from '../util'

const fragment = `
uniform sampler2D uCharacters;
uniform float uCharactersCount;
uniform float uCellSize;
uniform bool uInvert;
uniform vec3 uColor;
const fragment = /* glsl */ `
uniform sampler2D uCharacters;
uniform float uCharactersCount;
uniform float uCellSize;
uniform bool uInvert;
uniform vec3 uColor;

const vec2 SIZE = vec2(16.);
const vec2 SIZE = vec2(16.);

vec3 greyscale(vec3 color, float strength) {
vec3 greyscale(vec3 color, float strength) {
float g = dot(color, vec3(0.299, 0.587, 0.114));
return mix(color, vec3(g), strength);
}
}

vec3 greyscale(vec3 color) {
vec3 greyscale(vec3 color) {
return greyscale(color, 1.0);
}
}

void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
vec2 cell = resolution / uCellSize;
vec2 grid = 1.0 / cell;
vec2 pixelizedUV = grid * (0.5 + floor(uv / grid));
Expand All @@ -43,7 +44,7 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor)
asciiCharacter.rgb = uColor * asciiCharacter.r;
asciiCharacter.a = pixelized.a;
outputColor = asciiCharacter;
}
}
`

interface IASCIIEffectProps {
Expand All @@ -53,6 +54,7 @@ interface IASCIIEffectProps {
cellSize?: number
color?: string
invert?: boolean
ref?: Ref<ASCIIEffect>
}

class ASCIIEffect extends Effect {
Expand All @@ -63,7 +65,7 @@ class ASCIIEffect extends Effect {
cellSize = 16,
color = '#ffffff',
invert = false,
}: IASCIIEffectProps = {}) {
}: Omit<IASCIIEffectProps, 'ref'> = {}) {
const uniforms = new Map<string, Uniform>([
['uCharacters', new Uniform(new Texture())],
['uCellSize', new Uniform(cellSize)],
Expand Down Expand Up @@ -114,22 +116,21 @@ class ASCIIEffect extends Effect {
}
}

export const ASCII = /* @__PURE__ */ forwardRef<ASCIIEffect, IASCIIEffectProps>(
(
{
font = 'arial',
characters = ` .:,'-^=*+?!|0#X%WM@`,
fontSize = 54,
cellSize = 16,
color = '#ffffff',
invert = false,
},
fref
) => {
const effect = useMemo(
() => new ASCIIEffect({ characters, font, fontSize, cellSize, color, invert }),
[characters, fontSize, cellSize, color, invert, font]
)
return <primitive ref={fref} object={effect} />
}
)
export function ASCII({
font = 'arial',
characters = ` .:,'-^=*+?!|0#X%WM@`,
fontSize = 54,
cellSize = 16,
color = '#ffffff',
invert = false,
ref,
}: IASCIIEffectProps) {
const effect = useMemo(
() => new ASCIIEffect({ characters, font, fontSize, cellSize, color, invert }),
[characters, fontSize, cellSize, color, invert, font]
)

useDispose(effect)

return <primitive ref={ref} object={effect} />
}
31 changes: 28 additions & 3 deletions src/effects/ChromaticAberration.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
import type { ReactThreeFiber } from '@react-three/fiber'
import { ChromaticAberrationEffect } from 'postprocessing'
import { type EffectProps, wrapEffect } from '../wrapEffect'
import type { Ref } from 'react'
import { useMemo } from 'react'
import { useDispose, useVector2 } from '../util'

export type ChromaticAberrationProps = EffectProps<typeof ChromaticAberrationEffect>
export const ChromaticAberration = /* @__PURE__ */ wrapEffect(ChromaticAberrationEffect)
export type ChromaticAberrationProps = Omit<
Partial<ConstructorParameters<typeof ChromaticAberrationEffect>[0]>,
'offset'
> & {
ref?: Ref<ChromaticAberrationEffect>
offset?: ReactThreeFiber.Vector2
}

export function ChromaticAberration({ ref, ...props }: ChromaticAberrationProps) {
const offset = useVector2(props, 'offset')

const effect = useMemo(
() =>
new ChromaticAberrationEffect({
...props,
offset,
} as ConstructorParameters<typeof ChromaticAberrationEffect>[0]),
[offset, props]
)

useDispose(effect)

return <primitive object={effect} ref={ref} />
}
30 changes: 16 additions & 14 deletions src/effects/ColorAverage.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { ColorAverageEffect, BlendFunction } from 'postprocessing'
import React, { Ref, forwardRef, useMemo } from 'react'

export type ColorAverageProps = Partial<{
blendFunction: BlendFunction
}>

export const ColorAverage = /* @__PURE__ */ forwardRef<ColorAverageEffect, ColorAverageProps>(function ColorAverage(
{ blendFunction = BlendFunction.NORMAL }: ColorAverageProps,
ref: Ref<ColorAverageEffect>
) {
/** Because ColorAverage blendFunction is not an object but a number, we have to define a custom prop "blendFunction" */
import { BlendFunction, ColorAverageEffect } from 'postprocessing'
import type { Ref } from 'react'
import { useMemo } from 'react'
import { useDispose } from '../util'

export type ColorAverageProps = {
blendFunction?: BlendFunction
ref?: Ref<ColorAverageEffect>
}

export function ColorAverage({ blendFunction = BlendFunction.NORMAL, ref }: ColorAverageProps) {
const effect = useMemo(() => new ColorAverageEffect(blendFunction), [blendFunction])
return <primitive ref={ref} object={effect} dispose={null} />
})

useDispose(effect)

return <primitive object={effect} ref={ref} />
}
60 changes: 29 additions & 31 deletions src/effects/DepthOfField.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { ReactThreeFiber } from '@react-three/fiber'
import { DepthOfFieldEffect, MaskFunction } from 'postprocessing'
import { Ref, forwardRef, useMemo, useEffect, useContext } from 'react'
import { ReactThreeFiber } from '@react-three/fiber'
import type { Ref } from 'react'
import { use, useMemo } from 'react'
import { type DepthPackingStrategies, type Texture, Vector3 } from 'three'
import { EffectComposerContext } from '../EffectComposer'
import { useDispose } from '../util'

type DOFProps = ConstructorParameters<typeof DepthOfFieldEffect>[1] &
export type DepthOfFieldProps = ConstructorParameters<typeof DepthOfFieldEffect>[1] &
Partial<{
ref: Ref<DepthOfFieldEffect>
target: ReactThreeFiber.Vector3
depthTexture: {
texture: Texture
Expand All @@ -16,28 +19,27 @@ type DOFProps = ConstructorParameters<typeof DepthOfFieldEffect>[1] &
blur: number
}>

export const DepthOfField = /* @__PURE__ */ forwardRef(function DepthOfField(
{
blendFunction,
worldFocusDistance,
worldFocusRange,
focusDistance,
focusRange,
focalLength,
bokehScale,
resolutionScale,
resolutionX,
resolutionY,
width,
height,
target,
depthTexture,
...props
}: DOFProps,
ref: Ref<DepthOfFieldEffect>
) {
const { camera } = useContext(EffectComposerContext)
export function DepthOfField({
ref,
blendFunction,
worldFocusDistance,
worldFocusRange,
focusDistance,
focusRange,
focalLength,
bokehScale,
resolutionScale,
resolutionX,
resolutionY,
width,
height,
target,
depthTexture,
...props
}: DepthOfFieldProps) {
const { camera } = use(EffectComposerContext)
const autoFocus = target != null

const effect = useMemo(() => {
const effect = new DepthOfFieldEffect(camera, {
blendFunction,
Expand Down Expand Up @@ -79,11 +81,7 @@ export const DepthOfField = /* @__PURE__ */ forwardRef(function DepthOfField(
depthTexture,
])

useEffect(() => {
return () => {
effect.dispose()
}
}, [effect])
useDispose(effect)

return <primitive {...props} ref={ref} object={effect} target={target} />
})
return <primitive {...props} object={effect} ref={ref} target={target} />
}
27 changes: 12 additions & 15 deletions src/effects/Glitch.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Vector2 } from 'three'
import { GlitchEffect, GlitchMode } from 'postprocessing'
import { Ref, forwardRef, useMemo, useLayoutEffect, useEffect } from 'react'
import { ReactThreeFiber, useThree } from '@react-three/fiber'
import { useVector2 } from '../util'
import { GlitchEffect, GlitchMode } from 'postprocessing'
import { Ref, useLayoutEffect, useMemo } from 'react'
import { useDispose, useVector2 } from '../util'

export type GlitchProps = ConstructorParameters<typeof GlitchEffect>[0] &
Partial<{
Expand All @@ -12,29 +11,27 @@ export type GlitchProps = ConstructorParameters<typeof GlitchEffect>[0] &
duration: ReactThreeFiber.Vector2
chromaticAberrationOffset: ReactThreeFiber.Vector2
strength: ReactThreeFiber.Vector2
ref?: Ref<GlitchEffect>
}>

export const Glitch = /* @__PURE__ */ forwardRef<GlitchEffect, GlitchProps>(function Glitch(
{ active = true, ...props }: GlitchProps,
ref: Ref<GlitchEffect>
) {
export function Glitch({ active = true, ref, ...props }: GlitchProps) {
const invalidate = useThree((state) => state.invalidate)
const delay = useVector2(props, 'delay')
const duration = useVector2(props, 'duration')
const strength = useVector2(props, 'strength')
const chromaticAberrationOffset = useVector2(props, 'chromaticAberrationOffset')

const effect = useMemo(
() => new GlitchEffect({ ...props, delay, duration, strength, chromaticAberrationOffset }),
[delay, duration, props, strength, chromaticAberrationOffset]
)

useLayoutEffect(() => {
effect.mode = active ? props.mode || GlitchMode.SPORADIC : GlitchMode.DISABLED
invalidate()
}, [active, effect, invalidate, props.mode])
useEffect(() => {
return () => {
effect.dispose?.()
}
}, [effect])
return <primitive ref={ref} object={effect} dispose={null} />
})

useDispose(effect)

return <primitive ref={ref} object={effect} />
}
16 changes: 10 additions & 6 deletions src/effects/GodRays.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { GodRaysEffect } from 'postprocessing'
import React, { Ref, forwardRef, useMemo, useContext, useLayoutEffect } from 'react'
import { Ref, RefObject, useContext, useLayoutEffect, useMemo } from 'react'
import { Mesh, Points } from 'three'
import { EffectComposerContext } from '../EffectComposer'
import { resolveRef } from '../util'
import { resolveRef, useDispose } from '../util'

type GodRaysProps = ConstructorParameters<typeof GodRaysEffect>[2] & {
sun: Mesh | Points | React.RefObject<Mesh | Points>
sun: Mesh | Points | RefObject<Mesh | Points>
ref?: Ref<GodRaysEffect>
}

export const GodRays = /* @__PURE__ */ forwardRef(function GodRays(props: GodRaysProps, ref: Ref<GodRaysEffect>) {
export function GodRays({ ref, ...props }: GodRaysProps) {
const { camera } = useContext(EffectComposerContext)
const effect = useMemo(() => new GodRaysEffect(camera, resolveRef(props.sun), props), [camera, props])
useLayoutEffect(() => void (effect.lightSource = resolveRef(props.sun)), [effect, props.sun])
return <primitive ref={ref} object={effect} dispose={null} />
})

useDispose(effect)

return <primitive ref={ref} object={effect} />
}
17 changes: 12 additions & 5 deletions src/effects/Grid.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import React, { Ref, forwardRef, useMemo, useLayoutEffect } from 'react'
import { GridEffect } from 'postprocessing'
import { useThree } from '@react-three/fiber'
import { GridEffect } from 'postprocessing'
import { Ref, useLayoutEffect, useMemo } from 'react'
import { useDispose } from '../util'

type GridProps = ConstructorParameters<typeof GridEffect>[0] &
Partial<{
size: {
width: number
height: number
}
ref: Ref<GridEffect>
}>

export const Grid = /* @__PURE__ */ forwardRef(function Grid({ size, ...props }: GridProps, ref: Ref<GridEffect>) {
export function Grid({ size, ref, ...props }: GridProps) {
const invalidate = useThree((state) => state.invalidate)

const effect = useMemo(() => new GridEffect(props), [props])

useLayoutEffect(() => {
if (size) effect.setSize(size.width, size.height)
invalidate()
}, [effect, size, invalidate])
return <primitive ref={ref} object={effect} dispose={null} />
})

useDispose(effect)

return <primitive ref={ref} object={effect} />
}
Loading
Loading