pmndrs / react-postprocessing

📬 postprocessing for react-three-fiber
https://docs.pmnd.rs/react-postprocessing
MIT License
1.09k stars 101 forks source link

Custom Effect not working -- Example in documentation is not TypeScript-compatible. #159

Open GabeDahl opened 1 year ago

GabeDahl commented 1 year ago

My overall goal is to implement Pixi.js's Twist Filter as a custom Effect in an React-Three-Fiber app. Here's a working example of the filter's shader ported to a Three.js ShaderMaterial.

I'm not getting any errors from the program, so I'm not sure what's wrong. In addition, I just copy/pasted this example from the docs and TypeScript immediately yelled at me. Any help is greatly appreciated!

TwistEffect.js

import { forwardRef, useMemo } from 'react'
import { Uniform, Vector2, Vector4, Texture } from 'three'
import { Effect } from 'postprocessing'
import fragmentShader from '../../../shaders/twist.frag'

let _radius
let _angle
let _offset

// Effect implementation
class TwistEffectImp extends Effect {

 constructor() {
    const radius = 0.9
    const angle = 30
    const offset = new Vector2(0.0, 0.0)
    super('TwisterEffect', fragmentShader, {
      uniforms: new Map([
        ['radius', new Uniform(radius)],
        ['angle', new Uniform(angle)],
        ['offset', new Uniform(offset)],
      ]),
    })
    _radius = radius
    _angle = angle
    _offset = offset
  }

  update(renderer, inputBuffer, deltaTime) {
    this.uniforms.get('radius').value = _radius
    this.uniforms.get('angle').value = _angle
    this.uniforms.get('offset').value = _offset
  }
}

// Effect component
export const TwistEffect = forwardRef(({ param }, ref) => {
  const effect = useMemo(() => new TwistEffectImp(param), [param])
  return <primitive ref={ref} object={effect} />
})

twist.frag

uniform float radius;
uniform float angle;
uniform vec2 offset;

vec2 mapCoord(vec2 coord ) {
    coord *= resolution;
    return coord;
}

vec2 unmapCoord(vec2 coord ) {
    coord /= resolution;
    return coord;
}

vec2 twist(vec2 coord) {
    coord -= offset;
    float dist = length(coord);
    if (dist < radius) {
        float ratioDist = (radius - dist) / radius;
        float angleMod = ratioDist * ratioDist * angle;
        float s = sin(angleMod);
        float c = cos(angleMod);
        coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);
    }
    coord += offset;
    return coord;
}

void mainUv(inout vec2 uv) {
    vec2 coord = mapCoord(uv);
    coord = twist(coord);
    coord = unmapCoord(coord);
    gl_FragColor = texture2D(inputBuffer, coord );
}
jayhxmo commented 1 year ago

Did you find a solution to this?