Vignette.js 1.99 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
  float dist = distance(uv, finger);
  float amp2 = pow(1.0 - dist, 2.0);
27 28
  float colorSeparation = 0.02 * mix(amp2, 1.0, 0.5);
  vec2 orientation = vec2(1.0, 0.0);
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
29 30
  gl_FragColor = vec4(
    vec3(
31 32
    texture2D(texture, lookup(colorSeparation * orientation, amp2)).r,
    texture2D(texture, lookup(-colorSeparation * orientation, amp2)).g,
33 34
    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
35 36 37 38 39 40 41
}
`
  }
});


class Vignette extends React.Component {
42 43 44 45 46 47 48 49 50 51 52 53 54
  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
55
  render () {
56
    const { width, height, time, source } = this.props;
57
    const { finger } = this.state;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
58
    return <GL.View
59 60 61
      onStartShouldSetResponder={() => true}
      onMoveShouldSetResponder={() => true}
      onResponderMove={this.onResponderMove}
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
62 63 64 65 66
      shader={shaders.imageVignette}
      style={{ width, height }}
      opaque={false}
      uniforms={{
        time: time,
67
        freq: 10 + 2 * Math.sin(0.7*time),
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
68
        texture: source,
69
        amp: 0.05 + Math.max(0, 0.03*Math.cos(time)),
70 71
        moving: 0,
        finger: finger
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
72 73 74 75 76 77
      }}
    />;
  }
}

module.exports = Vignette;