Skip to content

Instantly share code, notes, and snippets.

@gre
Last active November 19, 2016 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gre/5b9496decf9a1090bf55324e218836ac to your computer and use it in GitHub Desktop.
Save gre/5b9496decf9a1090bf55324e218836ac to your computer and use it in GitHub Desktop.
This is using an experimental incoming version of gl-react, stay tuned
//@flow
import React, { Component } from "react";
import { Bus } from "gl-react";
import { Surface } from "gl-react-dom";
import colorScales from "./colorScales";
const shaders = Shaders.create({
colorify: {
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D image;
uniform sampler2D colorScale; // used as a lookup texture
uniform float legend;
float monochrome (vec3 c) {
return 0.2125 * c.r + 0.7154 * c.g + 0.0721 * c.b;
}
void main() {
vec4 imgC = texture2D(image, uv / vec2(1.0, 1.0-legend) - vec2(0.0, legend));
vec4 scaleC = texture2D(colorScale, vec2(monochrome(imgC.rgb), 0.5));
float legendArea = step(uv.y, legend);
gl_FragColor =
step(uv.y, legend - 0.02) * texture2D(colorScale, uv) +
step(legend, uv.y) * vec4(scaleC.rgb, imgC.a * scaleC.a);
}
`,
},
});
const Colorify = ({ children: image, colorScale, legend=0.06, interpolation }) =>
<Node
shader={shaders.colorify}
uniformsOptions={{ colorScale: { interpolation } }}
uniforms={{ legend, colorScale, image, }}
/>;
// We first implement a component <Video> that is like <video>
// but provides a onFrame hook so we can efficiently only render
// if when it effectively changes.
import raf from "raf";
class Video extends Component {
componentDidMount() {
const loop = () => {
this._raf = raf(loop);
const {video} = this.refs;
if (!video) return;
const currentTime = video.currentTime;
// Optimization that only call onFrame if time changes
if (currentTime !== this.currentTime) {
this.currentTime = currentTime;
this.props.onFrame(currentTime);
}
};
this._raf = raf(loop);
}
componentWillUnmount() {
raf.cancel(this._raf);
}
render() {
const { onFrame, ...rest } = this.props; // eslint-disable-line
return <video {...rest} ref="video" />;
}
}
// We can give our <Video> component a <WebCamSource> to have webcam stream!
class WebCamSource extends Component {
state = { src: null };
componentWillMount() {
navigator.mediaDevices.getUserMedia({ video: true }).then(stream =>
this.setState({ src: URL.createObjectURL(stream) }));
}
render() {
const {src} = this.state;
return src ? <source src={src} /> : null;
}
}
class Example extends Component {
render() {
const { interpolation, color } = this.props;
return (
<Surface width={480} height={360}>
<Colorify colorScale={colorScales[color]} interpolation={interpolation}>
{redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video> }
</Colorify>
</Surface>
);
}
static defaultProps = {
interpolation: "linear",
color: Object.keys(colorScales)[0],
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment