Vignette.js 2.03 KB
Newer Older
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const React = require("react-native");
const GL = require("gl-react-native");

const shaders = GL.Shaders.create({
  imageVignette: {
    frag: `
precision highp float;
varying vec2 uv;

uniform float time;
uniform float amp;
uniform float freq;
uniform sampler2D texture;
uniform float moving;

16
uniform vec2 finger;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
17

18
vec2 lookup (vec2 offset, float amp2) {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
19
  return mod(
20
    uv + amp2 * amp * vec2(cos(freq*(uv.x+offset.x)+time),sin(freq*(uv.y+offset.x)+time)) + vec2(moving * time/10.0, 0.0),
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
21 22 23 24
    vec2(1.0));
}

void main() {
25 26 27 28 29
  float dist = distance(uv, finger);
  float amp2 = pow(1.0 - dist, 2.0);
  float colorSeparation = 0.1 * amp2;
  float a = atan(uv.y-finger.y, uv.x-finger.x);
  vec2 delta = vec2(cos(a), sin(a));
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
30 31
  gl_FragColor = vec4(
    vec3(
32 33 34 35
    texture2D(texture, lookup(colorSeparation * delta, amp2)).r,
    texture2D(texture, lookup(-colorSeparation * delta, amp2)).g,
    texture2D(texture, lookup(vec2(0.0), amp2)).b),
    1.0-min(0.95, pow(1.8 * distance(uv, finger), 4.0) + 0.5 * pow(distance(fract(50.0 * uv.y), 0.5), 2.0)));
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
36 37 38 39 40 41 42
}
`
  }
});


class Vignette extends React.Component {
43 44 45 46 47 48 49 50 51 52 53 54 55
  constructor (props) {
    super(props);
    this.onResponderMove = this.onResponderMove.bind(this);
    this.state = {
      finger: [0.5, 0.5]
    };
  }
  onResponderMove (evt) {
    const { width, height } = this.props;
    const { locationX, locationY } = evt.nativeEvent;
    this.setState({ finger: [locationX/width, 1-locationY/height] });
  }

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
56 57
  render () {
    const { width, height, time, i, source } = this.props;
58
    const { finger } = this.state;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
59
    return <GL.View
60 61 62
      onStartShouldSetResponder={() => true}
      onMoveShouldSetResponder={() => true}
      onResponderMove={this.onResponderMove}
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
63 64 65 66 67
      shader={shaders.imageVignette}
      style={{ width, height }}
      opaque={false}
      uniforms={{
        time: time,
68
        freq: 10 + 2 * Math.sin(0.7*time + i),
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
69
        texture: source,
70 71 72
        amp: 0.05 + Math.max(0, 0.03*i*Math.cos(time + 2*i)),
        moving: 0,
        finger: finger
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
73 74 75 76 77 78
      }}
    />;
  }
}

module.exports = Vignette;