Skip to content

Commit

Permalink
Merge pull request #138 from gre/more-advanced-loop
Browse files Browse the repository at this point in the history
Introduces Uniform.backbufferFrom(node)
  • Loading branch information
gre authored Jul 18, 2017
2 parents 9ecefbc + 53804cf commit 5aada7f
Show file tree
Hide file tree
Showing 14 changed files with 491 additions and 224 deletions.
Binary file added packages/cookbook/src/examples/blurfeedback/1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/cookbook/src/examples/blurfeedback/2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 50 additions & 0 deletions packages/cookbook/src/examples/blurfeedback/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//@flow
import React, { Component } from "react";
import { NearestCopy, LinearCopy, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import { BlurXY } from "../blurxy";
import { images } from "./meta";
import timeLoop from "../../HOC/timeLoop";

const ContinuousBlur = timeLoop(BlurXY);

export default class Example extends Component {
state = {
buffering: false
};
componentWillReceiveProps({ image, refreshId }: *) {
if (image !== this.props.image || refreshId !== this.props.refreshId) {
this.setState({ buffering: false }); // start again with the image
}
}
onDraw = () => {
if (!this.state.buffering) {
// after a first draw without buffering, enable it back
this.setState({ buffering: true });
}
};
getMainBuffer = () => {
const { main } = this.refs;
return main ? Uniform.backbufferFrom(main.getNodeRef()) : null;
};
render() {
const { image, factor } = this.props;
const { buffering } = this.state;
return (
<Surface width={400} height={300} preload={images}>
<NearestCopy>
<LinearCopy backbuffering ref="main" onDraw={this.onDraw}>
<ContinuousBlur factor={factor}>
{!buffering ? image : this.getMainBuffer}
</ContinuousBlur>
</LinearCopy>
</NearestCopy>
</Surface>
);
}
static defaultProps = {
image: require("./1.jpg"),
factor: 0,
refreshId: 0
};
}
51 changes: 51 additions & 0 deletions packages/cookbook/src/examples/blurfeedback/index.source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module.exports=`//@flow
import React, { Component } from "react";
import { NearestCopy, LinearCopy, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import { BlurXY } from "../blurxy";
import { images } from "./meta";
import timeLoop from "../../HOC/timeLoop";
const ContinuousBlur = timeLoop(BlurXY);
export default class Example extends Component {
state = {
buffering: false
};
componentWillReceiveProps({ image, refreshId }: *) {
if (image !== this.props.image || refreshId !== this.props.refreshId) {
this.setState({ buffering: false }); // start again with the image
}
}
onDraw = () => {
if (!this.state.buffering) {
// after a first draw without buffering, enable it back
this.setState({ buffering: true });
}
};
getMainBuffer = () => {
const { main } = this.refs;
return main ? Uniform.backbufferFrom(main.getNodeRef()) : null;
};
render() {
const { image, factor } = this.props;
const { buffering } = this.state;
return (
<Surface width={400} height={300} preload={images}>
<NearestCopy>
<LinearCopy backbuffering ref="main" onDraw={this.onDraw}>
<ContinuousBlur factor={factor}>
{!buffering ? image : this.getMainBuffer}
</ContinuousBlur>
</LinearCopy>
</NearestCopy>
</Surface>
);
}
static defaultProps = {
image: require("./1.jpg"),
factor: 0,
refreshId: 0
};
}
`
43 changes: 43 additions & 0 deletions packages/cookbook/src/examples/blurfeedback/meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import markdown from "../../markdown";
import ImagesPicker from "../../toolbox/ImagesPicker";
import makeFloatSlider from "../../toolbox/makeFloatSlider";

export const images = [
require("./1.jpg"),
require("./2.jpg"),
require("./3.jpg")
];

export const toolbox = [
{
prop: "factor",
title: "Blur",
Editor: makeFloatSlider(0, 8, 0.2)
},
{
prop: "image",
title: "Image",
Editor: ImagesPicker,
style: { width: 400 },
imageStyle: { maxWidth: 56, maxHeight: 56, marginBottom: 16 },
images
},
{
prop: "refreshId",
title: "",
Editor: ({ onChange, value }) =>
<button
style={{ fontSize: "1.4em", lineHeight: "1.4em" }}
onClick={() => onChange(value + 1)}
>
REFRESH
</button>
}
];

export const title = "Blur feedback";

export const desc = markdown`
buffering the result of a blur back to the source
`;
1 change: 1 addition & 0 deletions packages/cookbook/src/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ blurmap
blurmapmouse
blurmapdyn
blurimgtitle
blurfeedback
gol
golglider
golrot
Expand Down
20 changes: 17 additions & 3 deletions packages/gl-react/src/LinearCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,36 @@ import React, { Component } from "react";
import Node from "./Node";
import copyShader from "./copyShader";

type Props = {|
type Props = {
children?: any
|};
};

/**
* copy pixel with a linear interpolation
* @prop {any} children content to render
*/
class LinearCopy extends Component {
props: Props;
_node: ?Node;
/**
* get a reference to the underlying Node instance
* @return {Node}
*/
getNodeRef() {
return this._node;
}
_onRef = (node: Node) => {
this._node = node;
};
render() {
const { children: t } = this.props;
const { children: t, ...rest } = this.props;
return (
<Node
{...rest}
ref={this._onRef}
shader={copyShader}
blendFunc={{ src: "one", dst: "one minus src alpha" }}
uniformsOptions={{ t: { interpolation: "linear" } }}
uniforms={{ t }}
/>
);
Expand Down
19 changes: 16 additions & 3 deletions packages/gl-react/src/NearestCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,33 @@ import React, { Component } from "react";
import Node from "./Node";
import copyShader from "./copyShader";

type Props = {|
type Props = {
children?: any
|};
};

/**
* copy pixel with no interpolation (nearest pixel)
* @prop {any} children content to render
*/
class NearestCopy extends Component {
props: Props;
_node: ?Node;
/**
* get a reference to the underlying Node instance
* @return {Node}
*/
getNodeRef() {
return this._node;
}
_onRef = (node: Node) => {
this._node = node;
};
render() {
const { children: t } = this.props;
const { children: t, ...rest } = this.props;
return (
<Node
{...rest}
ref={this._onRef}
shader={copyShader}
blendFunc={{ src: "one", dst: "one minus src alpha" }}
uniformsOptions={{ t: { interpolation: "nearest" } }}
Expand Down
53 changes: 46 additions & 7 deletions packages/gl-react/src/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ const isBackbuffer = (obj: *) => {
return obj === Uniform.Backbuffer;
};

const isBackbufferFrom = (obj: *) =>
obj && typeof obj === "object" && obj.type === "BackbufferFrom";

const isTextureSizeGetter = (obj: *) =>
obj && typeof obj === "object" && obj.type === "TextureSize";

Expand Down Expand Up @@ -469,7 +472,6 @@ export default class Node extends Component {
if (this.backbuffer) {
this.backbuffer.syncSize(...nextWidthHeight);
}
// FIXME should we do same for backbuffer?
invariant(
nextProps.backbuffering === this.drawProps.backbuffering,
"Node backbuffering prop must not changed. (not yet supported)"
Expand Down Expand Up @@ -558,6 +560,15 @@ export default class Node extends Component {
return framebuffer.color;
}
getGLBackbufferOutput(): WebGLTexture {
const { backbuffer } = this;
invariant(
backbuffer,
"Node#getGLBackbufferOutput: backbuffer is not defined. Make sure `backbuffering` prop is defined"
);
return backbuffer.color;
}
/**
* Imperatively set the props with a partial subset of props to apply.
* This is an escape hatch to perform a redraw with different props without having to trigger a new React draw. Only use it when reaching a performance bottleneck.
Expand Down Expand Up @@ -844,7 +855,8 @@ export default class Node extends Component {
result: ?{
directTexture?: ?WebGLTexture,
directTextureSize?: ?[number, number],
glNode?: Node
glNode?: Node,
glNodePickBackbuffer?: boolean
};
if (typeof obj === "function") {
Expand All @@ -866,10 +878,34 @@ export default class Node extends Component {
`${nodeName}, uniform ${uniformKeyName}: you must set \`backbuffering\` on Node when using Backbuffer`
);
}
result = {
directTexture: this.getGLOutput(),
directTextureSize: this.getGLSize()
};
result = { glNode: this, glNodePickBackbuffer: true };
} else if (isBackbufferFrom(obj)) {
// backbuffer of another node/bus
invariant(
typeof obj === "object",
"invalid backbufferFromNode. Got: %s",
obj
);
let node = obj.node;
if (node instanceof Bus) {
node = node.getGLRenderableNode();
invariant(
node,
"backbufferFromNode(bus) but bus.getGLRenderableNode() is %s",
node
);
}
invariant(
node instanceof Node,
"invalid backbufferFromNode(obj): obj must be an instanceof Node or Bus. Got: %s",
obj
);
if (!node.drawProps.backbuffering) {
console.warn(
`${nodeName}, uniform ${uniformKeyName}: you must set \`backbuffering\` on the Node referenced in backbufferFrom(${node.getGLName()})`
);
}
result = { glNode: node, glNodePickBackbuffer: true };
} else if (obj instanceof Node) {
// maybe it's a Node?
dependency = obj;
Expand Down Expand Up @@ -944,7 +980,10 @@ export default class Node extends Component {
const texture: WebGLTexture =
(result &&
(result.directTexture ||
(result.glNode && result.glNode.getGLOutput()))) ||
(result.glNode &&
(result.glNodePickBackbuffer
? result.glNode.getGLBackbufferOutput()
: result.glNode.getGLOutput())))) ||
glSurface.getEmptyTexture();
if (textureUnits.has(texture)) {
// FIXME different uniform options on a same texture is not supported
Expand Down
3 changes: 3 additions & 0 deletions packages/gl-react/src/Uniform.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const Uniform = {
* the framebuffer size itself
*/
Resolution: "_Resolution_",

backbufferFrom: (node: *) => ({ type: "BackbufferFrom", node }),

/**
* Inject the size of a given Texture input
* @param {any} obj the texture input object
Expand Down
Loading

0 comments on commit 5aada7f

Please sign in to comment.