Merge pull request #132 from gre/fix/116

introduce Uniform object, drop legacy

see https://github.com/gre/gl-react/pull/132
This commit is contained in:
Gaëtan Renaudeau 2017-07-06 19:23:35 +02:00 committed by GitHub
commit d997fd2d6e
49 changed files with 1821 additions and 1721 deletions

View File

@ -1,4 +1,3 @@
import React, { Component } from "react";
import {
StyleSheet,
@ -6,63 +5,63 @@ import {
ScrollView,
View,
Platform,
Linking,
Linking
} from "react-native";
import getGLReactImplementation from "./gl-react-implementation";
const { Surface, name } = getGLReactImplementation();
import {Node, Shaders, GLSL, Backbuffer, LinearCopy} from "gl-react";
import { Node, Shaders, GLSL, Uniform, LinearCopy } from "gl-react";
import timeLoop from "./HOC/timeLoop";
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: "#fff",
backgroundColor: "#fff"
},
container: {
paddingVertical: 20,
flexDirection: "column",
flexDirection: "column"
},
list: {
flex: 1,
flex: 1
},
subHeader: {
padding: 10,
backgroundColor: "#f9f9f9",
backgroundColor: "#f9f9f9"
},
subHeaderText: {
color: "#333",
fontSize: 12,
fontStyle: "italic",
fontStyle: "italic"
},
title: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
justifyContent: "center"
},
titleText: {
fontWeight: "bold",
color: "#fff",
fontSize: 18,
fontSize: 18
},
ex1: {
flexDirection: "column",
flexDirection: "column"
},
code: {
backgroundColor: "transparent",
color: "#282c34",
fontFamily: Platform.select({
android: "monospace",
ios: "Courier New",
ios: "Courier New"
}),
fontSize: 9,
padding: 8,
width: 250,
width: 250
},
link: {
fontSize: 14,
textDecorationLine: "underline",
},
textDecorationLine: "underline"
}
});
const shaders = Shaders.create({
@ -81,14 +80,15 @@ void main () {
}`
},
HelloGL: {
// uniforms are variables from JS. We pipe blue uniform into blue output color
// uniforms are variables from JS. We pipe blue uniform into blue output color
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform float red;
void main() {
gl_FragColor = vec4(red, uv.x, uv.y, 1.0);
}` },
}`
},
Rotate: {
frag: GLSL`
precision highp float;
@ -102,20 +102,22 @@ void main() {
p.x < 0.0 || p.x > 1.0 || p.y < 0.0 || p.y > 1.0
? vec4(0.0)
: texture2D(children, p);
}` }
}`
}
});
const MotionBlur = ({ children, persistence }: *) =>
const MotionBlur = ({ children, persistence }: *) => (
<Node
shader={shaders.MotionBlur}
backbuffering
uniforms={{ children, backbuffer: Backbuffer, persistence }}
/>;
uniforms={{ children, backbuffer: Uniform.Backbuffer, persistence }}
/>
);
// We can make a <HelloBlue blue={0.5} /> that will render the concrete <Node/>
class HelloGL extends Component {
props: {
red: number,
red: number
};
render() {
const { red } = this.props;
@ -127,11 +129,13 @@ class Rotate extends Component {
props: {
scale: number,
angle: number,
children: any,
children: any
};
render() {
const { angle, scale, children } = this.props;
return <Node shader={shaders.Rotate} uniforms={{ scale, angle, children }} />;
return (
<Node shader={shaders.Rotate} uniforms={{ scale, angle, children }} />
);
}
}
@ -154,8 +158,7 @@ class Ex1 extends Component {
</MotionBlur>
</LinearCopy>
</Surface>
<Text style={styles.code}>{
`<Surface style={{width:250,height:250}}>
<Text style={styles.code}>{`<Surface style={{width:250,height:250}}>
<LinearCopy>
<MotionBlur persistence={${persistence.toFixed(2)}}>
<Rotate scale={${scale.toFixed(2)}} angle={${angle.toFixed(2)}}>
@ -163,8 +166,7 @@ class Ex1 extends Component {
</Rotate>
</MotionBlur>
</LinearCopy>
</Surface>`
}</Text>
</Surface>`}</Text>
</View>
);
}
@ -174,24 +176,27 @@ const Ex1Loop = timeLoop(Ex1);
class Link extends React.Component {
render() {
const {url} = this.props;
return <Text style={styles.link} onPress={() => Linking.openURL(url)}>
{url}
</Text>;
const { url } = this.props;
return (
<Text style={styles.link} onPress={() => Linking.openURL(url)}>
{url}
</Text>
);
}
}
export default class Home extends React.Component {
static route = {
navigationBar: {
renderTitle: () =>
renderTitle: () => (
<View style={styles.title}>
<Text style={styles.titleText}>{name}</Text>
</View>
},
)
}
};
props: {
navigator: *,
navigator: *
};
render() {
return (

View File

@ -1,12 +1,13 @@
//@flow
import React from "react";
import {Backbuffer,Shaders,Node,GLSL,NearestCopy} from "gl-react";
import getGLReactImplementation from "../../gl-react-implementation"; const { Surface } = getGLReactImplementation();
import { Uniform, Shaders, Node, GLSL, NearestCopy } from "gl-react";
import getGLReactImplementation from "../../gl-react-implementation";
const { Surface } = getGLReactImplementation();
import timeLoop from "../../HOC/timeLoop";
export const shaders = Shaders.create({
InitGameOfLife: {
// returns white or black randomly
// returns white or black randomly
frag: GLSL`
precision highp float;
// i
@ -20,7 +21,7 @@ void main() {
}`
},
GameOfLife: {
// implement Game Of Life.
// implement Game Of Life.
frag: GLSL`
precision highp float;
varying vec2 uv;
@ -48,36 +49,37 @@ const refreshEveryTicks = 20;
export const GameOfLife = ({ tick }) => {
// Changing size is "destructive" and will reset the Game of Life state
const size = 16 * (1+Math.floor(tick/refreshEveryTicks));
const size = 16 * (1 + Math.floor(tick / refreshEveryTicks));
// However, we can conditionally change shader/uniforms,
// React reconciliation will preserve the same <Node> instance,
// and our Game of Life state will get preserved!
return tick%refreshEveryTicks===0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Backbuffer, // Use previous frame buffer as a texture
size,
}}
/>;
return tick % refreshEveryTicks === 0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Uniform.Backbuffer, // Use previous frame buffer as a texture
size
}}
/>;
};
const GameOfLifeLoop = timeLoop(GameOfLife, { refreshRate: 20 });
export default ({ width }) =>
export default ({ width }) => (
<Surface style={{ width, height: width }}>
<NearestCopy>
<GameOfLifeLoop />
</NearestCopy>
</Surface>
);

View File

@ -1,6 +1,6 @@
//@flow
import React, { Component } from "react";
import { Backbuffer, Node, NearestCopy } from "gl-react";
import { Uniform, Node, NearestCopy } from "gl-react";
import getGLReactImplementation from "../../gl-react-implementation";
const { Surface } = getGLReactImplementation();
import { shaders } from "../gol";
@ -16,8 +16,8 @@ const GameOfLifeLoop = timeLoop(
backbuffering
sync
uniforms={{
t: tick === 0 ? gliderGunImage : Backbuffer,
size,
t: tick === 0 ? gliderGunImage : Uniform.Backbuffer,
size
}}
/>
),
@ -32,7 +32,7 @@ export default class Example extends Component {
style={{ width, height: width }}
preload={[
// preload textures before starting rendering
gliderGunImage,
gliderGunImage
]}
>
<NearestCopy>

View File

@ -7,8 +7,9 @@
//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL, Backbuffer } from "gl-react";
import getGLReactImplementation from "../../gl-react-implementation"; const { Surface } = getGLReactImplementation();
import { Shaders, Node, GLSL, Uniform } from "gl-react";
import getGLReactImplementation from "../../gl-react-implementation";
const { Surface } = getGLReactImplementation();
import ndarray from "ndarray";
import timeLoop from "../../HOC/timeLoop";
@ -339,7 +340,7 @@ void main () {
class IBEXLogic extends Component {
state = {
seed: Math.random(),
seed: Math.random()
};
shouldComponentUpdate({ tick }) {
return tick !== this.props.tick;
@ -351,61 +352,58 @@ class IBEXLogic extends Component {
initialState,
forestGrowFactor,
waterFactor,
fireFactor,
fireFactor
} = this.props;
const { seed } = this.state;
let draw=false, drawPosition=[0,0], drawRadius=0, drawElement=0;
let draw = false, drawPosition = [0, 0], drawRadius = 0, drawElement = 0;
let w = Math.random() < waterFactor, f = Math.random() < fireFactor;
if (w && f) {
if (Math.random() * waterFactor - Math.random() * fireFactor > 0) {
f = false;
}
else {
} else {
w = false;
}
}
if (w) {
draw = true;
drawPosition=[
size[0]*Math.random(),
size[1]*(0.8 + 0.2 * Math.random()),
drawPosition = [
size[0] * Math.random(),
size[1] * (0.8 + 0.2 * Math.random())
];
drawRadius = 4;
drawElement = 3;
console.log(drawElement, drawPosition, drawPosition);
}
else if (f) {
} else if (f) {
draw = true;
drawPosition=[
size[0]*Math.random(),
0,
];
drawPosition = [size[0] * Math.random(), 0];
drawRadius = 4;
drawElement = 2;
console.log(drawElement, drawPosition, drawPosition);
}
return <Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick===0 ? initialState : Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor,
}}
/>;
return (
<Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick === 0 ? initialState : Uniform.Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor
}}
/>
);
}
}
@ -416,86 +414,89 @@ var colors = [
[0.40, 0.75, 0.90], // 3: water
[0.60, 0.00, 0.00], // 4: volcano (fire spawner)
[0.30, 0.60, 0.70], // 5: source (water spawner)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
];
const IBEXRender = ({ size, children: state }) =>
const IBEXRender = ({ size, children: state }) => (
<Node
shader={shaders.IBEXRender}
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state,
size,
CL: colors,
CL: colors
}}
/>;
/>
);
const Game = timeLoop(class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time,
};
const Game = timeLoop(
class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time
};
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000/speed;
if (time-lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta,
};
}
});
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000 / speed;
if (time - lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta
};
}
});
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const { tick } = this.state;
return (
<IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>
);
}
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const {
tick,
} = this.state;
return <IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>;
}
});
);
// This should be implemented in a shader (it's a cellular automaton too)
// but it's how it was done in the game
function generate (startX: number, worldSize: [number,number]) {
function generate(startX: number, worldSize: [number, number]) {
var worldPixelRawBuf = new Uint8Array(worldSize[0] * worldSize[1] * 4);
var worldPixelBuf = new Uint8Array(worldSize[0] * worldSize[1]);
var waterInGeneration = 0;
var volcanoInGeneration = 0;
var w = worldSize[0], h = worldSize[1];
function step (a, b, x) {
return Math.max(0, Math.min((x-a) / (b-a), 1));
function step(a, b, x) {
return Math.max(0, Math.min((x - a) / (b - a), 1));
}
function affectColor (buf, i, c) {
function affectColor(buf, i, c) {
buf[i] = ~~(256 * c / 9);
buf[i+3] = 1;
buf[i + 3] = 1;
}
function get (b, x, y) {
function get(b, x, y) {
if (x >= 0 && x < w && y >= 0 && y < h) {
return b[x + y * w];
}
return y > 50 ? 1 : 0;
}
function set (b, x, y, e) {
function set(b, x, y, e) {
if (x >= 0 && x < w && y >= 0 && y < h) {
b[x + y * w] = e;
}
@ -505,9 +506,9 @@ function generate (startX: number, worldSize: [number,number]) {
for (x = startX; x < worldSize[0]; ++x) {
for (y = 0; y < worldSize[1]; ++y) {
e = +(Math.random() >
0.22
+ 0.3 * (step(0, 20, y)
+ step(worldSize[1]-20, worldSize[1] - 2, y)));
0.22 +
0.3 *
(step(0, 20, y) + step(worldSize[1] - 20, worldSize[1] - 2, y)));
set(worldPixelBuf, x, y, e);
}
}
@ -519,17 +520,25 @@ function generate (startX: number, worldSize: [number,number]) {
var me = get(cur, x, y);
var sum =
0.1 * me +
(0.9 + 0.1 * Math.random()) * (get(cur, x-1, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x+1, y-1)?1:0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x-1, y)?1:0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x+1, y)?1:0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x-1, y+1)?1:0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y+1)?1:0) +
(1.0 - 0.1 * Math.random()) * (get(cur, x+1, y+1?1:0));
let e = +(sum <= 6 + (Math.random()-0.5) * (1-k/K));
if (e && sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)) e = 5;
if (e && sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)) e = 4;
(0.9 + 0.1 * Math.random()) * (get(cur, x - 1, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x + 1, y - 1) ? 1 : 0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x - 1, y) ? 1 : 0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x + 1, y) ? 1 : 0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x - 1, y + 1) ? 1 : 0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y + 1) ? 1 : 0) +
(1.0 - 0.1 * Math.random()) * get(cur, x + 1, y + 1 ? 1 : 0);
let e = +(sum <= 6 + (Math.random() - 0.5) * (1 - k / K));
if (
e &&
sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)
)
e = 5;
if (
e &&
sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)
)
e = 4;
set(swp, x, y, e);
}
}
@ -541,17 +550,25 @@ function generate (startX: number, worldSize: [number,number]) {
for (i = 0; i < worldPixelBuf.length; ++i) {
affectColor(worldPixelRawBuf, 4 * i, worldPixelBuf[i]);
}
return ndarray(worldPixelRawBuf, [ worldSize[0], worldSize[1], 4]).transpose(1, 0, 2).step(1, -1, 1);
return ndarray(worldPixelRawBuf, [worldSize[0], worldSize[1], 4])
.transpose(1, 0, 2)
.step(1, -1, 1);
}
const size = [200,200];
const size = [200, 200];
export default class Example extends Component {
state = {
initialState: generate(0, size),
initialState: generate(0, size)
};
render() {
const { forestGrowFactor, fireFactor, waterFactor, speed, width } = this.props;
const {
forestGrowFactor,
fireFactor,
waterFactor,
speed,
width
} = this.props;
const { initialState } = this.state;
return (
<Surface style={{ width, height: width }}>
@ -571,11 +588,10 @@ export default class Example extends Component {
speed: 60,
forestGrowFactor: 1,
fireFactor: 0,
waterFactor: 0,
waterFactor: 0
};
}
/**
* Game Rule Interactions.
*

View File

@ -1,8 +1,8 @@
import React, {Component} from "react";
import {Link} from "react-router";
import React, { Component } from "react";
import { Link } from "react-router";
import Code from "./Code";
import {Surface} from "gl-react-dom";
import {Node, Shaders, GLSL, Backbuffer, LinearCopy} from "gl-react";
import { Surface } from "gl-react-dom";
import { Node, Shaders, GLSL, Uniform, LinearCopy } from "gl-react";
import timeLoop from "./HOC/timeLoop";
import "./Dashboard.css";
import Inspector from "./Inspector";
@ -23,14 +23,15 @@ void main () {
}`
},
HelloGL: {
// uniforms are variables from JS. We pipe blue uniform into blue output color
// uniforms are variables from JS. We pipe blue uniform into blue output color
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform float red;
void main() {
gl_FragColor = vec4(red, uv.x, uv.y, 1.0);
}` },
}`
},
Rotate: {
frag: GLSL`
precision highp float;
@ -44,20 +45,22 @@ void main() {
p.x < 0.0 || p.x > 1.0 || p.y < 0.0 || p.y > 1.0
? vec4(0.0)
: texture2D(children, p);
}` }
}`
}
});
const MotionBlur = ({ children, persistence }) =>
const MotionBlur = ({ children, persistence }) => (
<Node
shader={shaders.MotionBlur}
backbuffering
uniforms={{ children, backbuffer: Backbuffer, persistence }}
/>;
uniforms={{ children, backbuffer: Uniform.Backbuffer, persistence }}
/>
);
// We can make a <HelloBlue blue={0.5} /> that will render the concrete <Node/>
class HelloGL extends Component {
props: {
red: number,
red: number
};
render() {
const { red } = this.props;
@ -69,11 +72,13 @@ class Rotate extends Component {
props: {
scale: number,
angle: number,
children: any,
children: any
};
render() {
const { angle, scale, children } = this.props;
return <Node shader={shaders.Rotate} uniforms={{ scale, angle, children }} />;
return (
<Node shader={shaders.Rotate} uniforms={{ scale, angle, children }} />
);
}
}
@ -81,7 +86,7 @@ class Ex1 extends Component {
props: { time: number };
state = {
showCode: false,
showInspector: false,
showInspector: false
};
onShowCode = () => {
this.setState({ showCode: true });
@ -97,37 +102,40 @@ class Ex1 extends Component {
const scale = 0.70 + 0.40 * Math.cos(0.001 * time);
const angle = 2 * Math.PI * (0.5 + 0.5 * Math.cos(0.001 * time));
return (
<div className="ex">
<header>
<Surface width={200} height={200}>
<LinearCopy>
<MotionBlur persistence={persistence}>
<Rotate scale={scale} angle={angle}>
<HelloGL red={red} />
</Rotate>
</MotionBlur>
</LinearCopy>
</Surface>
{ !showCode
? <div onClick={this.onShowCode} className="showcode">SHOW ME THE CODE!</div>
:
<Code>{
` <Surface width={200} height={200}>
<div className="ex">
<header>
<Surface width={200} height={200}>
<LinearCopy>
<MotionBlur persistence={persistence}>
<Rotate scale={scale} angle={angle}>
<HelloGL red={red} />
</Rotate>
</MotionBlur>
</LinearCopy>
</Surface>
{!showCode
? <div onClick={this.onShowCode} className="showcode">
SHOW ME THE CODE!
</div>
: <Code>{` <Surface width={200} height={200}>
<MotionBlur persistence={${persistence.toFixed(2)}}>
<Rotate scale={${scale.toFixed(2)}} angle={${angle.toFixed(2)}}>
<HelloGL red={${red.toFixed(1)}} />
</Rotate>
</MotionBlur>
</Surface>`
}</Code> }
</header>
{ showCode
?
!showInspector
? <div onClick={this.onShowInspector} className="showunderthehood">SHOW ME UNDER THE HOOD!</div>
: <Inspector />
: null }
</div>
</Surface>`}</Code>}
</header>
{showCode
? !showInspector
? <div
onClick={this.onShowInspector}
className="showunderthehood"
>
SHOW ME UNDER THE HOOD!
</div>
: <Inspector />
: null}
</div>
);
}
}
@ -136,25 +144,31 @@ const Ex1Loop = timeLoop(Ex1);
export default class Dashboard extends Component {
render() {
return <div className="dashboard">
<h2>
gl-react is a <a href="http://facebook.github.io/react/">React</a> library to write and compose WebGL shaders.
</h2>
<Ex1Loop />
<nav>
<Link to="/hellogl">
Checkout more examples
</Link>
<a href="http://greweb.me/2016/12/gl-react-v3/">
gl-react-v3 release article
</a>
<a href="http://github.com/gre/gl-react">
Explore source code on Github
</a>
<a href="https://gitter.im/gl-react">
Chat with us
</a>
</nav>
</div>;
return (
<div className="dashboard">
<h2>
gl-react is a
{" "}
<a href="http://facebook.github.io/react/">React</a>
{" "}
library to write and compose WebGL shaders.
</h2>
<Ex1Loop />
<nav>
<Link to="/hellogl">
Checkout more examples
</Link>
<a href="http://greweb.me/2016/12/gl-react-v3/">
gl-react-v3 release article
</a>
<a href="http://github.com/gre/gl-react">
Explore source code on Github
</a>
<a href="https://gitter.im/gl-react">
Chat with us
</a>
</nav>
</div>
);
}
}

View File

@ -1,4 +1,4 @@
import React, {Component} from "react";
import React, { Component } from "react";
import PropTypes from "prop-types";
const encodeQueryValue = value => JSON.stringify(value);
@ -18,8 +18,7 @@ const decodeQuery = query => {
if (query.hasOwnProperty(k)) {
try {
query[k] = decodeQueryValue(query[k]);
}
catch (e) {
} catch (e) {
console.warn(e);
delete query[k];
}
@ -30,7 +29,7 @@ const decodeQuery = query => {
export default class ExamplePage extends Component {
static contextTypes = {
router: PropTypes.object.isRequired,
router: PropTypes.object.isRequired
};
setToolState = (obj: any) => {
@ -51,38 +50,43 @@ export default class ExamplePage extends Component {
const props = {
setToolState: this.setToolState,
...Example.defaultProps,
...decodeQuery(query),
...decodeQuery(query)
};
return <div id={path} className="example">
<div className="desc">{desc}</div>
<div className="rendering">
<Example {...props} />
return (
<div id={path} className="example">
<div className="desc">
{desc}
</div>
<div className="rendering">
<Example {...props} />
</div>
{toolbox
? <div className="toolbox">
{toolbox.map((field, i) =>
<div key={i} className="field">
{field.title
? <h3>
{typeof field.title === "function"
? field.title(props[field.prop])
: field.title}
</h3>
: null}
{field.Editor
? <field.Editor
{...field}
value={props[field.prop]}
onChange={this.onChangeField(field.prop)}
/>
: null}
</div>
)}
{ToolboxFooter ? <ToolboxFooter {...props} /> : null}
</div>
: null}
<div className="desc">
{descAfter}
</div>
</div>
{ toolbox
? <div className="toolbox">
{toolbox.map((field, i) =>
<div key={i} className="field">
{ field.title
? <h3>{
typeof field.title==="function"
? field.title(props[field.prop])
: field.title
}</h3>
: null }
{ field.Editor
? <field.Editor
{...field}
value={props[field.prop]}
onChange={this.onChangeField(field.prop)}
/>
: null }
</div>)}
{ ToolboxFooter
? <ToolboxFooter {...props} />
: null}
</div>
: null }
<div className="desc">{descAfter}</div>
</div>;
);
}
}

View File

@ -6,7 +6,7 @@ import {
VisitorLogger,
Node,
Bus,
Backbuffer,
Uniform,
listSurfaces
} from "gl-react";
import raf from "raf";
@ -175,7 +175,7 @@ class UniformValue extends Component {
}
return Array.isArray(type)
? <span className={"value-array " + classType(type)}>
{type.map((type, i) => (
{type.map((type, i) =>
<UniformValue
id={id + "[" + i + "]"}
key={i}
@ -184,7 +184,7 @@ class UniformValue extends Component {
type={type}
info={info && info[i]}
/>
))}
)}
</span>
: <span className={"value " + classType(type)}>
<span className="val">
@ -334,17 +334,21 @@ class MetaInfo extends Component {
nodeId={node.id}
anchorId={dependency.id}
/>
: obj === Backbuffer
? <AnchorHook
id={"rec_" + node.id + "_" + id}
nodeId={node.id}
anchorId={node.id}
/>
: null}
: obj === Uniform.Backbuffer
? <AnchorHook
id={"rec_" + node.id + "_" + id}
nodeId={node.id}
anchorId={node.id}
/>
: null}
{dependency
? dependency.getGLShortName()
: typeof obj === "string"
? <a href={obj} target="_blank">{obj}</a>
: obj === Uniform.Backbuffer
? "Backbuffer"
: typeof obj === "string"
? <a href={obj} target="_blank">
{obj}
</a>
: formatObject(obj)}
</span>
);
@ -529,10 +533,10 @@ class InspectorBox extends Component {
style={{ left: pos[0], top: pos[1] }}
className={
"box" +
(cls ? " " + cls : "") +
(recentDraw ? " recent-draw" : "") +
(grabbed ? " grabbed" : "") +
(minimized ? " minimized" : "")
(cls ? " " + cls : "") +
(recentDraw ? " recent-draw" : "") +
(grabbed ? " grabbed" : "") +
(minimized ? " minimized" : "")
}
>
<header onMouseDown={this.onMouseDown}>
@ -547,8 +551,12 @@ class InspectorBox extends Component {
{children}
<footer onClick={this.onClickMinimize}>
<span className="minimize"></span>
<span className="dim">{width}{height}</span>
<span className="mode">{mode}</span>
<span className="dim">
{width}{height}
</span>
<span className="mode">
{mode}
</span>
</footer>
</div>
);
@ -570,7 +578,7 @@ class Uniforms extends PureComponent {
return (
<div className="uniforms">
{preparedUniforms &&
preparedUniforms.map(u => (
preparedUniforms.map(u =>
<div key={u.key} className={"uniform " + classType(u.type)}>
<span
className="name"
@ -591,7 +599,7 @@ class Uniforms extends PureComponent {
/>
</span>
</div>
))}
)}
</div>
);
}
@ -628,17 +636,17 @@ class SVGConnectionLine extends PureComponent {
className="connection-line"
d={
`M${anchorX},${anchorY} ` +
`L${anchorX + s},${anchorY} ` +
`C${anchorX + t},${anchorY} ` +
(recursive
? `${anchorX + t},${anchorY - anchorYOff} ` +
`${anchorX + s},${anchorY - anchorYOff} ` +
`L${hookX - s},${anchorY - anchorYOff} ` +
`C${hookX - t},${anchorY - anchorYOff} `
: "") +
`${hookX - t * (reversedHook ? -1 : 1)},${hookY} ` +
`${hookX - s * (reversedHook ? -1 : 1)},${hookY} ` +
`L${hookX},${hookY}`
`L${anchorX + s},${anchorY} ` +
`C${anchorX + t},${anchorY} ` +
(recursive
? `${anchorX + t},${anchorY - anchorYOff} ` +
`${anchorX + s},${anchorY - anchorYOff} ` +
`L${hookX - s},${anchorY - anchorYOff} ` +
`C${hookX - t},${anchorY - anchorYOff} `
: "") +
`${hookX - t * (reversedHook ? -1 : 1)},${hookY} ` +
`${hookX - s * (reversedHook ? -1 : 1)},${hookY} ` +
`L${hookX},${hookY}`
}
/>
);
@ -1433,13 +1441,13 @@ export default class Inspector extends Component {
<div className="no-surface">
<h2>No Surface is currently inspected. Select one of these:</h2>
<ul>
{listSurfaces().map(surface => (
{listSurfaces().map(surface =>
<li key={surface.id}>
<span onClick={() => this.setSurface(surface)}>
{surface.getGLName()}
</span>
</li>
))}
)}
</ul>
</div>
</div>
@ -1462,11 +1470,11 @@ export default class Inspector extends Component {
onChange={this.onSelectChange}
>
<option value="">(none)</option>
{listSurfaces().map(surface => (
{listSurfaces().map(surface =>
<option key={surface.id} value={surface.id}>
{surface.getGLName()}
</option>
))}
)}
</select>
<label>
<input

View File

@ -1,6 +1,6 @@
//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL, Bus, Backbuffer } from "gl-react";
import { Shaders, Node, GLSL, Bus, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import gameBuild from "./build";
@ -118,7 +118,6 @@ void main() {
1.0);
}
`
},
player: {
frag: GLSL`
@ -213,118 +212,130 @@ void main() {
}
});
const Blur1D =
({ dim, dir, children: t }) =>
<Node shader={shaders.blur1d} uniforms={{ dim, dir, t }} />;
const Blur1D = ({ dim, dir, children: t }) => (
<Node shader={shaders.blur1d} uniforms={{ dim, dir, t }} />
);
export default class Example extends Component {
render () {
const {showCanvas} = this.props;
const {pt,pl,ex,J,P,s,F,k,S,W,H} =
// HACK to just render the game
this._ ? this._.getWebGLParams() :
({ pt: 0, pl: 0, ex: 0, J: 0, P: 0, s: 0, F: 0, k: [0,0], W: 2, H: 2, S: 0 });
const dim = [ W, H ];
render() {
const { showCanvas } = this.props;
const { pt, pl, ex, J, P, s, F, k, S, W, H } =
// HACK to just render the game
this._
? this._.getWebGLParams()
: {
pt: 0,
pl: 0,
ex: 0,
J: 0,
P: 0,
s: 0,
F: 0,
k: [0, 0],
W: 2,
H: 2,
S: 0
};
const dim = [W, H];
return (
<div style={{ background: "black" }} ref="container">
<div style={{ background: "black" }} ref="container">
<Surface width={W} height={H} pixelRatio={1}>
<Surface width={W} height={H} pixelRatio={1}>
<Bus ref="laser">
<Node
shader={shaders.laser}
uniforms={{ t: () => this.refs.gameCanvas }}
/>
</Bus>
<Bus ref="player">
<Blur1D dim={dim} dir={[ 0, 2 ]}>
<Blur1D dim={dim} dir={[ 6, 0 ]}>
<Blur1D dim={dim} dir={[ 2, 2 ]}>
<Blur1D dim={dim} dir={[ -2, 2 ]}>
<Node
shader={shaders.player}
uniforms={{ pt, pl, ex, J, P, S }}
/>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
<Bus ref="glare">
<Blur1D dim={dim} dir={[ 2, -4 ]}>
<Bus ref="laser">
<Node
shader={shaders.glare}
uniforms={{ t: () => this.refs.laser }}
shader={shaders.laser}
uniforms={{ t: () => this.refs.gameCanvas }}
/>
</Blur1D>
</Bus>
</Bus>
<Bus ref="glareCursor">
<Blur1D dim={dim} dir={[ 4, -8 ]}>
{() => this.refs.glare}
</Blur1D>
</Bus>
<Bus ref="glareBlurred">
<Blur1D dim={dim} dir={[ 0, 1 ]}>
<Blur1D dim={dim} dir={[ 1, 0 ]}>
<Blur1D dim={dim} dir={[ -0.5, 0.5 ]}>
<Blur1D dim={dim} dir={[ 0.5, 0.5 ]}>
{() => this.refs.laser
//FIXME this should be glare instead.
//but i think there is a bug in gl-react!
}
<Bus ref="player">
<Blur1D dim={dim} dir={[0, 2]}>
<Blur1D dim={dim} dir={[6, 0]}>
<Blur1D dim={dim} dir={[2, 2]}>
<Blur1D dim={dim} dir={[-2, 2]}>
<Node
shader={shaders.player}
uniforms={{ pt, pl, ex, J, P, S }}
/>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
</Bus>
<Bus ref="glare">
<Blur1D dim={dim} dir={[2, -4]}>
<Node
shader={shaders.glare}
uniforms={{ t: () => this.refs.laser }}
/>
</Blur1D>
</Bus>
<Bus ref="glareCursor">
<Blur1D dim={dim} dir={[4, -8]}>
{() => this.refs.glare}
</Blur1D>
</Bus>
<Bus ref="glareBlurred">
<Blur1D dim={dim} dir={[0, 1]}>
<Blur1D dim={dim} dir={[1, 0]}>
<Blur1D dim={dim} dir={[-0.5, 0.5]}>
<Blur1D dim={dim} dir={[0.5, 0.5]}>
{() => this.refs.laser
//FIXME this should be glare instead.
//but i think there is a bug in gl-react!
}
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
<Bus ref="persistence">
<Node
shader={shaders.persistence}
backbuffering
uniforms={{
t: this.refs.glareBlurred,
r: Uniform.Backbuffer
}}
/>
</Bus>
<Bus ref="persistence">
<Node
shader={shaders.persistence}
backbuffering
shader={shaders.game}
uniforms={{
t: this.refs.glareBlurred,
r: Backbuffer
G: () => this.refs.laser,
R: () => this.refs.persistence,
B: () => this.refs.glareBlurred,
L: () => this.refs.glareCursor,
E: () => this.refs.player,
s,
F,
k
}}
/>
</Bus>
</Surface>
<Node
shader={shaders.game}
uniforms={{
G: () => this.refs.laser,
R: () => this.refs.persistence,
B: () => this.refs.glareBlurred,
L: () => this.refs.glareCursor,
E: () => this.refs.player,
s,
F,
k
}} />
</Surface>
<canvas id="c" ref="gameCanvas" hidden={!showCanvas} />
<canvas id="c" ref="gameCanvas" hidden={!showCanvas} />
<div style={{ textAlign: "center", padding: 20 }}>
<button onClick={this.sendAsteroid}>
SEND ASTEROID!
</button>
<div style={{ textAlign: "center", padding: 20 }}>
<button onClick={this.sendAsteroid}>
SEND ASTEROID!
</button>
</div>
</div>
</div>
);
}
_: any;
componentDidMount () {
this._ = gameBuild(
this.refs.container,
this.refs.gameCanvas,
() => this.forceUpdate()
componentDidMount() {
this._ = gameBuild(this.refs.container, this.refs.gameCanvas, () =>
this.forceUpdate()
);
}
componentWillUnmount() {
@ -334,6 +345,6 @@ export default class Example extends Component {
sendAsteroid = () => window._behindAsteroids_send();
static defaultProps = {
showCanvas: false,
showCanvas: false
};
}

View File

@ -1,6 +1,6 @@
module.exports=`//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL, Bus, Backbuffer } from "gl-react";
import { Shaders, Node, GLSL, Bus, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import gameBuild from "./build";
@ -118,7 +118,6 @@ void main() {
1.0);
}
\`
},
player: {
frag: GLSL\`
@ -213,118 +212,130 @@ void main() {
}
});
const Blur1D =
({ dim, dir, children: t }) =>
<Node shader={shaders.blur1d} uniforms={{ dim, dir, t }} />;
const Blur1D = ({ dim, dir, children: t }) => (
<Node shader={shaders.blur1d} uniforms={{ dim, dir, t }} />
);
export default class Example extends Component {
render () {
const {showCanvas} = this.props;
const {pt,pl,ex,J,P,s,F,k,S,W,H} =
// HACK to just render the game
this._ ? this._.getWebGLParams() :
({ pt: 0, pl: 0, ex: 0, J: 0, P: 0, s: 0, F: 0, k: [0,0], W: 2, H: 2, S: 0 });
const dim = [ W, H ];
render() {
const { showCanvas } = this.props;
const { pt, pl, ex, J, P, s, F, k, S, W, H } =
// HACK to just render the game
this._
? this._.getWebGLParams()
: {
pt: 0,
pl: 0,
ex: 0,
J: 0,
P: 0,
s: 0,
F: 0,
k: [0, 0],
W: 2,
H: 2,
S: 0
};
const dim = [W, H];
return (
<div style={{ background: "black" }} ref="container">
<div style={{ background: "black" }} ref="container">
<Surface width={W} height={H} pixelRatio={1}>
<Surface width={W} height={H} pixelRatio={1}>
<Bus ref="laser">
<Node
shader={shaders.laser}
uniforms={{ t: () => this.refs.gameCanvas }}
/>
</Bus>
<Bus ref="player">
<Blur1D dim={dim} dir={[ 0, 2 ]}>
<Blur1D dim={dim} dir={[ 6, 0 ]}>
<Blur1D dim={dim} dir={[ 2, 2 ]}>
<Blur1D dim={dim} dir={[ -2, 2 ]}>
<Node
shader={shaders.player}
uniforms={{ pt, pl, ex, J, P, S }}
/>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
<Bus ref="glare">
<Blur1D dim={dim} dir={[ 2, -4 ]}>
<Bus ref="laser">
<Node
shader={shaders.glare}
uniforms={{ t: () => this.refs.laser }}
shader={shaders.laser}
uniforms={{ t: () => this.refs.gameCanvas }}
/>
</Blur1D>
</Bus>
</Bus>
<Bus ref="glareCursor">
<Blur1D dim={dim} dir={[ 4, -8 ]}>
{() => this.refs.glare}
</Blur1D>
</Bus>
<Bus ref="glareBlurred">
<Blur1D dim={dim} dir={[ 0, 1 ]}>
<Blur1D dim={dim} dir={[ 1, 0 ]}>
<Blur1D dim={dim} dir={[ -0.5, 0.5 ]}>
<Blur1D dim={dim} dir={[ 0.5, 0.5 ]}>
{() => this.refs.laser
//FIXME this should be glare instead.
//but i think there is a bug in gl-react!
}
<Bus ref="player">
<Blur1D dim={dim} dir={[0, 2]}>
<Blur1D dim={dim} dir={[6, 0]}>
<Blur1D dim={dim} dir={[2, 2]}>
<Blur1D dim={dim} dir={[-2, 2]}>
<Node
shader={shaders.player}
uniforms={{ pt, pl, ex, J, P, S }}
/>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
</Bus>
<Bus ref="glare">
<Blur1D dim={dim} dir={[2, -4]}>
<Node
shader={shaders.glare}
uniforms={{ t: () => this.refs.laser }}
/>
</Blur1D>
</Bus>
<Bus ref="glareCursor">
<Blur1D dim={dim} dir={[4, -8]}>
{() => this.refs.glare}
</Blur1D>
</Bus>
<Bus ref="glareBlurred">
<Blur1D dim={dim} dir={[0, 1]}>
<Blur1D dim={dim} dir={[1, 0]}>
<Blur1D dim={dim} dir={[-0.5, 0.5]}>
<Blur1D dim={dim} dir={[0.5, 0.5]}>
{() => this.refs.laser
//FIXME this should be glare instead.
//but i think there is a bug in gl-react!
}
</Blur1D>
</Blur1D>
</Blur1D>
</Blur1D>
</Bus>
<Bus ref="persistence">
<Node
shader={shaders.persistence}
backbuffering
uniforms={{
t: this.refs.glareBlurred,
r: Uniform.Backbuffer
}}
/>
</Bus>
<Bus ref="persistence">
<Node
shader={shaders.persistence}
backbuffering
shader={shaders.game}
uniforms={{
t: this.refs.glareBlurred,
r: Backbuffer
G: () => this.refs.laser,
R: () => this.refs.persistence,
B: () => this.refs.glareBlurred,
L: () => this.refs.glareCursor,
E: () => this.refs.player,
s,
F,
k
}}
/>
</Bus>
</Surface>
<Node
shader={shaders.game}
uniforms={{
G: () => this.refs.laser,
R: () => this.refs.persistence,
B: () => this.refs.glareBlurred,
L: () => this.refs.glareCursor,
E: () => this.refs.player,
s,
F,
k
}} />
</Surface>
<canvas id="c" ref="gameCanvas" hidden={!showCanvas} />
<canvas id="c" ref="gameCanvas" hidden={!showCanvas} />
<div style={{ textAlign: "center", padding: 20 }}>
<button onClick={this.sendAsteroid}>
SEND ASTEROID!
</button>
<div style={{ textAlign: "center", padding: 20 }}>
<button onClick={this.sendAsteroid}>
SEND ASTEROID!
</button>
</div>
</div>
</div>
);
}
_: any;
componentDidMount () {
this._ = gameBuild(
this.refs.container,
this.refs.gameCanvas,
() => this.forceUpdate()
componentDidMount() {
this._ = gameBuild(this.refs.container, this.refs.gameCanvas, () =>
this.forceUpdate()
);
}
componentWillUnmount() {
@ -334,7 +345,7 @@ export default class Example extends Component {
sendAsteroid = () => window._behindAsteroids_send();
static defaultProps = {
showCanvas: false,
showCanvas: false
};
}
`

View File

@ -1,11 +1,12 @@
module.exports=`//@flow
import React, { PureComponent, Component, PropTypes } from "react";
import React, { PureComponent, Component } from "react";
import PropTypes from "prop-types";
import { Shaders, Node, GLSL, Bus, LinearCopy, connectSize } from "gl-react";
import { Surface } from "gl-react-dom";
import JSON2D from "react-json2d";
import {Blur1D} from "../blurxy";
import {Blur} from "../blurmulti";
import {BlurV} from "../blurmap";
import { Blur1D } from "../blurxy";
import { Blur } from "../blurmulti";
import { BlurV } from "../blurmap";
const shaders = Shaders.create({
ImageTitle: {
@ -42,54 +43,60 @@ gl_FragColor = vec4(
vec3(smoothstep(1.0, threshold, texture2D(t, uv).r)),
1.0);
}\`
},
}
});
const AveragePixels = ({ children, quality }) =>
<Blur1D
width={1}
height={1}
resolution={[ 1, 1 ]}
direction={[ 0, 0.1 ]}>
const AveragePixels = ({ children, quality }) => (
<Blur1D width={1} height={1} resolution={[1, 1]} direction={[0, 0.1]}>
<Blur1D
width={1}
height={quality}
resolution={[ 1, quality ]}
direction={[ 0.1, 0 ]}>
resolution={[1, quality]}
direction={[0.1, 0]}
>
{children}
</Blur1D>
</Blur1D>;
</Blur1D>
);
const TitleBlurMap = ({ children: title, threshold }) =>
const TitleBlurMap = ({ children: title, threshold }) => (
<Node
shader={shaders.TitleBlurMap}
uniforms={{
threshold,
t:
t: (
<Blur factor={4} passes={4} width={200} height={200}>
{title}
</Blur>
)
}}
width={64}
height={64}
/>;
/>
);
class Title extends PureComponent {
render () {
render() {
const { children, width, height } = this.props;
return <LinearCopy><JSON2D width={width} height={height}>{{
size: [ width, height ],
background: "#fff",
draws: [
{
"font": "bold 78px Didot,Georgia,serif",
"fillStyle": "#000",
"textBaseline": "top",
"textAlign": "center"
},
[ "fillText", children, width/2, 10, 84 ],
]
}}</JSON2D></LinearCopy>;
return (
<LinearCopy>
<JSON2D width={width} height={height}>
{{
size: [width, height],
background: "#fff",
draws: [
{
font: "bold 78px Didot,Georgia,serif",
fillStyle: "#000",
textBaseline: "top",
textAlign: "center"
},
["fillText", children, width / 2, 10, 84]
]
}}
</JSON2D>
</LinearCopy>
);
}
}
@ -99,50 +106,48 @@ class ImageTitleC extends Component {
height: PropTypes.number.isRequired,
children: PropTypes.any.isRequired,
text: PropTypes.string.isRequired,
colorThreshold: PropTypes.number.isRequired,
colorThreshold: PropTypes.number.isRequired
};
render() {
const { width, height, children: img, text, colorThreshold } = this.props;
return (
<Node
shader={shaders.ImageTitle}
uniforms={{
colorThreshold,
img,
imgBlurred:() => this.refs.imgBlurred,
title:() => this.refs.title,
imgTone:() => this.refs.imgTone,
blurMap:() => this.refs.blurMap,
}}>
<Node
shader={shaders.ImageTitle}
uniforms={{
colorThreshold,
img,
imgBlurred: () => this.refs.imgBlurred,
title: () => this.refs.title,
imgTone: () => this.refs.imgTone,
blurMap: () => this.refs.blurMap
}}
>
<Bus ref="title">
<Title width={width} height={height}>
{text}
</Title>
</Bus>
<Bus ref="title">
<Title width={width} height={height}>
{text}
</Title>
</Bus>
<Bus ref="blurMap">
<TitleBlurMap threshold={0.7}>
{() => this.refs.title}
</TitleBlurMap>
</Bus>
<Bus ref="blurMap">
<TitleBlurMap threshold={0.7}>
{() => this.refs.title}
</TitleBlurMap>
</Bus>
<Bus ref="imgTone">
<AveragePixels quality={8}>
{img}
</AveragePixels>
</Bus>
<Bus ref="imgTone">
<AveragePixels quality={8}>
{img}
</AveragePixels>
</Bus>
<Bus ref="imgBlurred">
<BlurV
map={() => this.refs.blurMap}
factor={4}
passes={4}>
{img}
</BlurV>
</Bus>
<Bus ref="imgBlurred">
<BlurV map={() => this.refs.blurMap} factor={4} passes={4}>
{img}
</BlurV>
</Bus>
</Node>
</Node>
);
}
}
@ -152,18 +157,18 @@ export default class Example extends Component {
render() {
const { title, colorThreshold, image } = this.props;
return (
<Surface width={450} height={300}>
<ImageTitle text={title} colorThreshold={colorThreshold}>
{image}
</ImageTitle>
</Surface>
<Surface width={450} height={300}>
<ImageTitle text={title} colorThreshold={colorThreshold}>
{image}
</ImageTitle>
</Surface>
);
}
static defaultProps = {
title: "Hello\\nSan Francisco\\n☻",
colorThreshold: 0.6,
image: require("./sf-6.jpg"),
image: require("./sf-6.jpg")
};
}
`

View File

@ -1,11 +1,11 @@
export const title = "GLSL live editor";
import "./glsledit.css";
import makeTextArea from "../../toolbox/makeTextArea";
export const title = "GLSL live editor";
export const toolbox = [
{ prop: "frag",
{
prop: "frag",
Editor: makeTextArea({
height: 400,
padding: 10,
@ -16,6 +16,7 @@ export const toolbox = [
color: "#ABB2BF",
fontSize: 10,
lineHeight: 1.5,
fontFamily: "Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace",
}) }
fontFamily: "Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace"
})
}
];

View File

@ -1,12 +1,12 @@
//@flow
import React from "react";
import {Backbuffer,Shaders,Node,GLSL,NearestCopy} from "gl-react";
import { Uniform, Shaders, Node, GLSL, NearestCopy } from "gl-react";
import { Surface } from "gl-react-dom";
import timeLoop from "../../HOC/timeLoop";
export const shaders = Shaders.create({
InitGameOfLife: {
// returns white or black randomly
// returns white or black randomly
frag: GLSL`
precision highp float;
// i
@ -20,7 +20,7 @@ void main() {
}`
},
GameOfLife: {
// implement Game Of Life.
// implement Game Of Life.
frag: GLSL`
precision highp float;
varying vec2 uv;
@ -48,36 +48,37 @@ const refreshEveryTicks = 20;
export const GameOfLife = ({ tick }) => {
// Changing size is "destructive" and will reset the Game of Life state
const size = 16 * (1+Math.floor(tick/refreshEveryTicks));
const size = 16 * (1 + Math.floor(tick / refreshEveryTicks));
// However, we can conditionally change shader/uniforms,
// React reconciliation will preserve the same <Node> instance,
// and our Game of Life state will get preserved!
return tick%refreshEveryTicks===0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Backbuffer, // Use previous frame buffer as a texture
size,
}}
/>;
return tick % refreshEveryTicks === 0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Uniform.Backbuffer, // Use previous frame buffer as a texture
size
}}
/>;
};
const GameOfLifeLoop = timeLoop(GameOfLife, { refreshRate: 20 });
export default () =>
export default () => (
<Surface width={384} height={384}>
<NearestCopy>
<GameOfLifeLoop />
</NearestCopy>
</Surface>
);

View File

@ -1,12 +1,12 @@
module.exports=`//@flow
import React from "react";
import {Backbuffer,Shaders,Node,GLSL,NearestCopy} from "gl-react";
import { Uniform, Shaders, Node, GLSL, NearestCopy } from "gl-react";
import { Surface } from "gl-react-dom";
import timeLoop from "../../HOC/timeLoop";
export const shaders = Shaders.create({
InitGameOfLife: {
// returns white or black randomly
// returns white or black randomly
frag: GLSL\`
precision highp float;
// i
@ -20,7 +20,7 @@ void main() {
}\`
},
GameOfLife: {
// implement Game Of Life.
// implement Game Of Life.
frag: GLSL\`
precision highp float;
varying vec2 uv;
@ -48,37 +48,38 @@ const refreshEveryTicks = 20;
export const GameOfLife = ({ tick }) => {
// Changing size is "destructive" and will reset the Game of Life state
const size = 16 * (1+Math.floor(tick/refreshEveryTicks));
const size = 16 * (1 + Math.floor(tick / refreshEveryTicks));
// However, we can conditionally change shader/uniforms,
// React reconciliation will preserve the same <Node> instance,
// and our Game of Life state will get preserved!
return tick%refreshEveryTicks===0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Backbuffer, // Use previous frame buffer as a texture
size,
}}
/>;
return tick % refreshEveryTicks === 0
? <Node
shader={shaders.InitGameOfLife}
width={size}
height={size}
backbuffering // makes Node holding 2 fbos that get swapped each draw time
sync // force <Node> to draw in sync each componentDidUpdate time
/>
: <Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: Uniform.Backbuffer, // Use previous frame buffer as a texture
size
}}
/>;
};
const GameOfLifeLoop = timeLoop(GameOfLife, { refreshRate: 20 });
export default () =>
export default () => (
<Surface width={384} height={384}>
<NearestCopy>
<GameOfLifeLoop />
</NearestCopy>
</Surface>
);
`

View File

@ -1,23 +1,27 @@
//@flow
import React, { Component } from "react";
import { Backbuffer, Node, NearestCopy } from "gl-react";
import { Uniform, Node, NearestCopy } from "gl-react";
import { Surface } from "gl-react-dom";
import {shaders} from "../gol";
import { shaders } from "../gol";
import timeLoop from "../../HOC/timeLoop";
import gliderGunImage from "./glider-gun-64.png";
const GameOfLifeLoop = timeLoop(({ tick, size }) =>
<Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: tick===0 ? gliderGunImage : Backbuffer,
size,
}}
/>, { refreshRate: 20 });
const GameOfLifeLoop = timeLoop(
({ tick, size }) => (
<Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: tick === 0 ? gliderGunImage : Uniform.Backbuffer,
size
}}
/>
),
{ refreshRate: 20 }
);
export default class Example extends Component {
render() {
@ -25,9 +29,11 @@ export default class Example extends Component {
<Surface
width={500}
height={500}
preload={[ // preload textures before starting rendering
preload={[
// preload textures before starting rendering
gliderGunImage
]}>
]}
>
<NearestCopy>
<GameOfLifeLoop size={64} />
</NearestCopy>

View File

@ -1,23 +1,27 @@
module.exports=`//@flow
import React, { Component } from "react";
import { Backbuffer, Node, NearestCopy } from "gl-react";
import { Uniform, Node, NearestCopy } from "gl-react";
import { Surface } from "gl-react-dom";
import {shaders} from "../gol";
import { shaders } from "../gol";
import timeLoop from "../../HOC/timeLoop";
import gliderGunImage from "./glider-gun-64.png";
const GameOfLifeLoop = timeLoop(({ tick, size }) =>
<Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: tick===0 ? gliderGunImage : Backbuffer,
size,
}}
/>, { refreshRate: 20 });
const GameOfLifeLoop = timeLoop(
({ tick, size }) => (
<Node
shader={shaders.GameOfLife}
width={size}
height={size}
backbuffering
sync
uniforms={{
t: tick === 0 ? gliderGunImage : Uniform.Backbuffer,
size
}}
/>
),
{ refreshRate: 20 }
);
export default class Example extends Component {
render() {
@ -25,9 +29,11 @@ export default class Example extends Component {
<Surface
width={500}
height={500}
preload={[ // preload textures before starting rendering
preload={[
// preload textures before starting rendering
gliderGunImage
]}>
]}
>
<NearestCopy>
<GameOfLifeLoop size={64} />
</NearestCopy>

View File

@ -1,18 +1,21 @@
import React from "react";
import markdown from "../../markdown";
export const title = "GameOfLife is initialized with a glider texture";
import gliderGun64png from "./glider-gun-64.png";
export const title = "GameOfLife is initialized with a glider texture";
export const desc = markdown`
**Game of Life** init with an image!
`;
export const descAfter = markdown`
Initial image state inspired from [wikipedia](https://en.wikipedia.org/wiki/Conway's_Game_of_Life).
${<br />}
${<a href={gliderGun64png}>
<img
alt=""
style={{ width: 128, imageRendering: "pixelated" }}
src={gliderGun64png}
/>
</a>}
${(
<a href={gliderGun64png}>
<img
alt=""
style={{ width: 128, imageRendering: "pixelated" }}
src={gliderGun64png}
/>
</a>
)}
`;

View File

@ -1,6 +1,6 @@
//@flow
import React, { Component } from "react";
import { Bus, Backbuffer, Node, Shaders, GLSL } from "gl-react";
import { Bus, Uniform, Node, Shaders, GLSL } from "gl-react";
import { Surface } from "gl-react-dom";
import { Video } from "../video";
import { WebCamSource } from "../webcam";
@ -13,22 +13,34 @@ const extraShaders = Shaders.create({
precision highp float;
varying vec2 uv;
uniform sampler2D gol, webcam;
uniform float webcamRatio;
void main () {
vec3 webcamC = texture2D(webcam, uv).rgb;
gl_FragColor = vec4(
vec3(1.0) * texture2D(gol, uv).r +
webcamC * mix(step(0.5, webcamC.r), 0.9, 0.2),
1.0);
vec2 aspect = vec2(max(1.0, 1.0/webcamRatio), max(1.0, webcamRatio));
vec2 p = uv * aspect + (1.0 - aspect) / 2.0;
if (0.0>p.x||1.0<p.x||0.0>p.y||1.0<p.y) {
gl_FragColor = vec4(0.0);
}
else {
vec3 webcamC = texture2D(webcam, p).rgb;
gl_FragColor = vec4(
vec3(1.0) * texture2D(gol, p).r +
webcamC * mix(step(0.5, webcamC.r), 0.9, 0.2),
1.0);
}
}
`,
},
`
}
});
const Display = ({ gol, webcam }) =>
<Node
shader={extraShaders.Display}
uniformsOptions={{ gol: { interpolation: "nearest" } }}
uniforms={{ gol, webcam }}
uniforms={{
gol,
webcam,
webcamRatio: Uniform.textureSizeRatio(webcam)
}}
/>;
const GameOfLife = ({ size, reset, resetTexture }) =>
@ -39,8 +51,8 @@ const GameOfLife = ({ size, reset, resetTexture }) =>
backbuffering
sync
uniforms={{
t: reset ? resetTexture : Backbuffer,
size,
t: reset ? resetTexture : Uniform.Backbuffer,
size
}}
/>;
@ -53,34 +65,37 @@ export default class Example extends Component {
render() {
const { reset, size } = this.state;
return (
<Surface
style={{ cursor: "pointer" }}
width={400}
height={400}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}>
<Surface
style={{ cursor: "pointer" }}
width={400}
height={400}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
>
<Bus ref="webcam">
{redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>}
</Bus>
<Bus ref="webcam">{ redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
}</Bus>
<Display
gol={
<GameOfLifeLoop
reset={reset}
size={size}
resetTexture={() => this.refs.webcam}
/>
}
webcam={() => this.refs.webcam}
/>
</Surface>
<Display
gol={
<GameOfLifeLoop
reset={reset}
size={size}
resetTexture={() => this.refs.webcam}
/>
}
webcam={() => this.refs.webcam}
/>
</Surface>
);
}
onMouseDown = () =>
this.setState({ reset: true, size: Math.floor(10 + 200*Math.random()*Math.random()) });
onMouseUp = () =>
this.setState({ reset: false });
this.setState({
reset: true,
size: Math.floor(10 + 200 * Math.random() * Math.random())
});
onMouseUp = () => this.setState({ reset: false });
}

View File

@ -1,6 +1,6 @@
module.exports=`//@flow
import React, { Component } from "react";
import { Bus, Backbuffer, Node, Shaders, GLSL } from "gl-react";
import { Bus, Uniform, Node, Shaders, GLSL } from "gl-react";
import { Surface } from "gl-react-dom";
import { Video } from "../video";
import { WebCamSource } from "../webcam";
@ -13,22 +13,34 @@ const extraShaders = Shaders.create({
precision highp float;
varying vec2 uv;
uniform sampler2D gol, webcam;
uniform float webcamRatio;
void main () {
vec3 webcamC = texture2D(webcam, uv).rgb;
gl_FragColor = vec4(
vec3(1.0) * texture2D(gol, uv).r +
webcamC * mix(step(0.5, webcamC.r), 0.9, 0.2),
1.0);
vec2 aspect = vec2(max(1.0, 1.0/webcamRatio), max(1.0, webcamRatio));
vec2 p = uv * aspect + (1.0 - aspect) / 2.0;
if (0.0>p.x||1.0<p.x||0.0>p.y||1.0<p.y) {
gl_FragColor = vec4(0.0);
}
else {
vec3 webcamC = texture2D(webcam, p).rgb;
gl_FragColor = vec4(
vec3(1.0) * texture2D(gol, p).r +
webcamC * mix(step(0.5, webcamC.r), 0.9, 0.2),
1.0);
}
}
\`,
},
\`
}
});
const Display = ({ gol, webcam }) =>
<Node
shader={extraShaders.Display}
uniformsOptions={{ gol: { interpolation: "nearest" } }}
uniforms={{ gol, webcam }}
uniforms={{
gol,
webcam,
webcamRatio: Uniform.textureSizeRatio(webcam)
}}
/>;
const GameOfLife = ({ size, reset, resetTexture }) =>
@ -39,8 +51,8 @@ const GameOfLife = ({ size, reset, resetTexture }) =>
backbuffering
sync
uniforms={{
t: reset ? resetTexture : Backbuffer,
size,
t: reset ? resetTexture : Uniform.Backbuffer,
size
}}
/>;
@ -53,35 +65,38 @@ export default class Example extends Component {
render() {
const { reset, size } = this.state;
return (
<Surface
style={{ cursor: "pointer" }}
width={400}
height={400}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}>
<Surface
style={{ cursor: "pointer" }}
width={400}
height={400}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
>
<Bus ref="webcam">
{redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>}
</Bus>
<Bus ref="webcam">{ redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
}</Bus>
<Display
gol={
<GameOfLifeLoop
reset={reset}
size={size}
resetTexture={() => this.refs.webcam}
/>
}
webcam={() => this.refs.webcam}
/>
</Surface>
<Display
gol={
<GameOfLifeLoop
reset={reset}
size={size}
resetTexture={() => this.refs.webcam}
/>
}
webcam={() => this.refs.webcam}
/>
</Surface>
);
}
onMouseDown = () =>
this.setState({ reset: true, size: Math.floor(10 + 200*Math.random()*Math.random()) });
onMouseUp = () =>
this.setState({ reset: false });
this.setState({
reset: true,
size: Math.floor(10 + 200 * Math.random() * Math.random())
});
onMouseUp = () => this.setState({ reset: false });
}
`

View File

@ -1,3 +1,3 @@
export const title = "WebCam stream + Game Of Life!";
export const desc =
`Click to reset Game Of Life (random size)`;
export const desc = `Click to reset Game Of Life (random size)`;
export const descAfter = `See also usage of Uniform.textureSizeRatio`;

View File

@ -7,7 +7,7 @@
//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL, Backbuffer } from "gl-react";
import { Shaders, Node, GLSL, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import ndarray from "ndarray";
import timeLoop from "../../HOC/timeLoop";
@ -339,7 +339,7 @@ void main () {
class IBEXLogic extends Component {
state = {
seed: Math.random(),
seed: Math.random()
};
shouldComponentUpdate({ tick }) {
return tick !== this.props.tick;
@ -351,61 +351,58 @@ class IBEXLogic extends Component {
initialState,
forestGrowFactor,
waterFactor,
fireFactor,
fireFactor
} = this.props;
const { seed } = this.state;
let draw=false, drawPosition=[0,0], drawRadius=0, drawElement=0;
let draw = false, drawPosition = [0, 0], drawRadius = 0, drawElement = 0;
let w = Math.random() < waterFactor, f = Math.random() < fireFactor;
if (w && f) {
if (Math.random() * waterFactor - Math.random() * fireFactor > 0) {
f = false;
}
else {
} else {
w = false;
}
}
if (w) {
draw = true;
drawPosition=[
size[0]*Math.random(),
size[1]*(0.8 + 0.2 * Math.random()),
drawPosition = [
size[0] * Math.random(),
size[1] * (0.8 + 0.2 * Math.random())
];
drawRadius = 4;
drawElement = 3;
console.log(drawElement, drawPosition, drawPosition);
}
else if (f) {
} else if (f) {
draw = true;
drawPosition=[
size[0]*Math.random(),
0,
];
drawPosition = [size[0] * Math.random(), 0];
drawRadius = 4;
drawElement = 2;
console.log(drawElement, drawPosition, drawPosition);
}
return <Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick===0 ? initialState : Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor,
}}
/>;
return (
<Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick === 0 ? initialState : Uniform.Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor
}}
/>
);
}
}
@ -416,86 +413,89 @@ var colors = [
[0.40, 0.75, 0.90], // 3: water
[0.60, 0.00, 0.00], // 4: volcano (fire spawner)
[0.30, 0.60, 0.70], // 5: source (water spawner)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
];
const IBEXRender = ({ size, children: state }) =>
const IBEXRender = ({ size, children: state }) => (
<Node
shader={shaders.IBEXRender}
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state,
size,
CL: colors,
CL: colors
}}
/>;
/>
);
const Game = timeLoop(class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time,
};
const Game = timeLoop(
class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time
};
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000/speed;
if (time-lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta,
};
}
});
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000 / speed;
if (time - lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta
};
}
});
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const { tick } = this.state;
return (
<IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>
);
}
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const {
tick,
} = this.state;
return <IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>;
}
});
);
// This should be implemented in a shader (it's a cellular automaton too)
// but it's how it was done in the game
function generate (startX: number, worldSize: [number,number]) {
function generate(startX: number, worldSize: [number, number]) {
var worldPixelRawBuf = new Uint8Array(worldSize[0] * worldSize[1] * 4);
var worldPixelBuf = new Uint8Array(worldSize[0] * worldSize[1]);
var waterInGeneration = 0;
var volcanoInGeneration = 0;
var w = worldSize[0], h = worldSize[1];
function step (a, b, x) {
return Math.max(0, Math.min((x-a) / (b-a), 1));
function step(a, b, x) {
return Math.max(0, Math.min((x - a) / (b - a), 1));
}
function affectColor (buf, i, c) {
function affectColor(buf, i, c) {
buf[i] = ~~(256 * c / 9);
buf[i+3] = 1;
buf[i + 3] = 1;
}
function get (b, x, y) {
function get(b, x, y) {
if (x >= 0 && x < w && y >= 0 && y < h) {
return b[x + y * w];
}
return y > 50 ? 1 : 0;
}
function set (b, x, y, e) {
function set(b, x, y, e) {
if (x >= 0 && x < w && y >= 0 && y < h) {
b[x + y * w] = e;
}
@ -505,9 +505,9 @@ function generate (startX: number, worldSize: [number,number]) {
for (x = startX; x < worldSize[0]; ++x) {
for (y = 0; y < worldSize[1]; ++y) {
e = +(Math.random() >
0.22
+ 0.3 * (step(0, 20, y)
+ step(worldSize[1]-20, worldSize[1] - 2, y)));
0.22 +
0.3 *
(step(0, 20, y) + step(worldSize[1] - 20, worldSize[1] - 2, y)));
set(worldPixelBuf, x, y, e);
}
}
@ -519,17 +519,25 @@ function generate (startX: number, worldSize: [number,number]) {
var me = get(cur, x, y);
var sum =
0.1 * me +
(0.9 + 0.1 * Math.random()) * (get(cur, x-1, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x+1, y-1)?1:0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x-1, y)?1:0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x+1, y)?1:0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x-1, y+1)?1:0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y+1)?1:0) +
(1.0 - 0.1 * Math.random()) * (get(cur, x+1, y+1?1:0));
let e = +(sum <= 6 + (Math.random()-0.5) * (1-k/K));
if (e && sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)) e = 5;
if (e && sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)) e = 4;
(0.9 + 0.1 * Math.random()) * (get(cur, x - 1, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x + 1, y - 1) ? 1 : 0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x - 1, y) ? 1 : 0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x + 1, y) ? 1 : 0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x - 1, y + 1) ? 1 : 0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y + 1) ? 1 : 0) +
(1.0 - 0.1 * Math.random()) * get(cur, x + 1, y + 1 ? 1 : 0);
let e = +(sum <= 6 + (Math.random() - 0.5) * (1 - k / K));
if (
e &&
sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)
)
e = 5;
if (
e &&
sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)
)
e = 4;
set(swp, x, y, e);
}
}
@ -541,14 +549,16 @@ function generate (startX: number, worldSize: [number,number]) {
for (i = 0; i < worldPixelBuf.length; ++i) {
affectColor(worldPixelRawBuf, 4 * i, worldPixelBuf[i]);
}
return ndarray(worldPixelRawBuf, [ worldSize[0], worldSize[1], 4]).transpose(1, 0, 2).step(1, -1, 1);
return ndarray(worldPixelRawBuf, [worldSize[0], worldSize[1], 4])
.transpose(1, 0, 2)
.step(1, -1, 1);
}
const size = [200,200];
const size = [200, 200];
export default class Example extends Component {
state = {
initialState: generate(0, size),
initialState: generate(0, size)
};
render() {
const { forestGrowFactor, fireFactor, waterFactor, speed } = this.props;
@ -571,11 +581,10 @@ export default class Example extends Component {
speed: 60,
forestGrowFactor: 1,
fireFactor: 0,
waterFactor: 0,
waterFactor: 0
};
}
/**
* Game Rule Interactions.
*

View File

@ -7,7 +7,7 @@ module.exports=`/**
//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL, Backbuffer } from "gl-react";
import { Shaders, Node, GLSL, Uniform } from "gl-react";
import { Surface } from "gl-react-dom";
import ndarray from "ndarray";
import timeLoop from "../../HOC/timeLoop";
@ -339,7 +339,7 @@ void main () {
class IBEXLogic extends Component {
state = {
seed: Math.random(),
seed: Math.random()
};
shouldComponentUpdate({ tick }) {
return tick !== this.props.tick;
@ -351,61 +351,58 @@ class IBEXLogic extends Component {
initialState,
forestGrowFactor,
waterFactor,
fireFactor,
fireFactor
} = this.props;
const { seed } = this.state;
let draw=false, drawPosition=[0,0], drawRadius=0, drawElement=0;
let draw = false, drawPosition = [0, 0], drawRadius = 0, drawElement = 0;
let w = Math.random() < waterFactor, f = Math.random() < fireFactor;
if (w && f) {
if (Math.random() * waterFactor - Math.random() * fireFactor > 0) {
f = false;
}
else {
} else {
w = false;
}
}
if (w) {
draw = true;
drawPosition=[
size[0]*Math.random(),
size[1]*(0.8 + 0.2 * Math.random()),
drawPosition = [
size[0] * Math.random(),
size[1] * (0.8 + 0.2 * Math.random())
];
drawRadius = 4;
drawElement = 3;
console.log(drawElement, drawPosition, drawPosition);
}
else if (f) {
} else if (f) {
draw = true;
drawPosition=[
size[0]*Math.random(),
0,
];
drawPosition = [size[0] * Math.random(), 0];
drawRadius = 4;
drawElement = 2;
console.log(drawElement, drawPosition, drawPosition);
}
return <Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick===0 ? initialState : Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor,
}}
/>;
return (
<Node
shader={shaders.IBEXLogic}
sync
backbuffering
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state: tick === 0 ? initialState : Uniform.Backbuffer,
SZ: size,
SD: seed,
TI: tick,
TS: 0, // tick start
RU: true, // logic running
ST: true, // render started
draw,
DP: drawPosition, // draw position
DR: drawRadius, // draw radius
DO: drawElement, // the element that is being drawn
forestGrowFactor
}}
/>
);
}
}
@ -416,86 +413,89 @@ var colors = [
[0.40, 0.75, 0.90], // 3: water
[0.60, 0.00, 0.00], // 4: volcano (fire spawner)
[0.30, 0.60, 0.70], // 5: source (water spawner)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
[0.15, 0.20, 0.27], // 6: wind left
[0.07, 0.12, 0.19], // 7: wind right
[0.20, 0.60, 0.20] // 8: grass (forest)
];
const IBEXRender = ({ size, children: state }) =>
const IBEXRender = ({ size, children: state }) => (
<Node
shader={shaders.IBEXRender}
uniformsOptions={{ state: { interpolation: "nearest" } }}
uniforms={{
state,
size,
CL: colors,
CL: colors
}}
/>;
/>
);
const Game = timeLoop(class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time,
};
const Game = timeLoop(
class extends Component {
state = {
tick: 0,
lastTickTime: this.props.time
};
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000/speed;
if (time-lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta,
};
}
});
componentWillReceiveProps({ time, speed }) {
this.setState(({ tick, lastTickTime }) => {
const delta = 1000 / speed;
if (time - lastTickTime > delta) {
return {
tick: tick + 1,
lastTickTime: lastTickTime + delta
};
}
});
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const { tick } = this.state;
return (
<IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>
);
}
}
render() {
const {
size,
initialState,
forestGrowFactor,
waterFactor,
fireFactor
} = this.props;
const {
tick,
} = this.state;
return <IBEXRender size={size}>
<IBEXLogic
initialState={initialState}
size={size}
tick={tick}
forestGrowFactor={forestGrowFactor}
waterFactor={waterFactor}
fireFactor={fireFactor}
/>
</IBEXRender>;
}
});
);
// This should be implemented in a shader (it's a cellular automaton too)
// but it's how it was done in the game
function generate (startX: number, worldSize: [number,number]) {
function generate(startX: number, worldSize: [number, number]) {
var worldPixelRawBuf = new Uint8Array(worldSize[0] * worldSize[1] * 4);
var worldPixelBuf = new Uint8Array(worldSize[0] * worldSize[1]);
var waterInGeneration = 0;
var volcanoInGeneration = 0;
var w = worldSize[0], h = worldSize[1];
function step (a, b, x) {
return Math.max(0, Math.min((x-a) / (b-a), 1));
function step(a, b, x) {
return Math.max(0, Math.min((x - a) / (b - a), 1));
}
function affectColor (buf, i, c) {
function affectColor(buf, i, c) {
buf[i] = ~~(256 * c / 9);
buf[i+3] = 1;
buf[i + 3] = 1;
}
function get (b, x, y) {
function get(b, x, y) {
if (x >= 0 && x < w && y >= 0 && y < h) {
return b[x + y * w];
}
return y > 50 ? 1 : 0;
}
function set (b, x, y, e) {
function set(b, x, y, e) {
if (x >= 0 && x < w && y >= 0 && y < h) {
b[x + y * w] = e;
}
@ -505,9 +505,9 @@ function generate (startX: number, worldSize: [number,number]) {
for (x = startX; x < worldSize[0]; ++x) {
for (y = 0; y < worldSize[1]; ++y) {
e = +(Math.random() >
0.22
+ 0.3 * (step(0, 20, y)
+ step(worldSize[1]-20, worldSize[1] - 2, y)));
0.22 +
0.3 *
(step(0, 20, y) + step(worldSize[1] - 20, worldSize[1] - 2, y)));
set(worldPixelBuf, x, y, e);
}
}
@ -519,17 +519,25 @@ function generate (startX: number, worldSize: [number,number]) {
var me = get(cur, x, y);
var sum =
0.1 * me +
(0.9 + 0.1 * Math.random()) * (get(cur, x-1, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y-1)?1:0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x+1, y-1)?1:0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x-1, y)?1:0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x+1, y)?1:0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x-1, y+1)?1:0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y+1)?1:0) +
(1.0 - 0.1 * Math.random()) * (get(cur, x+1, y+1?1:0));
let e = +(sum <= 6 + (Math.random()-0.5) * (1-k/K));
if (e && sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)) e = 5;
if (e && sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)) e = 4;
(0.9 + 0.1 * Math.random()) * (get(cur, x - 1, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x, y - 1) ? 1 : 0) +
(0.9 + 0.1 * Math.random()) * (get(cur, x + 1, y - 1) ? 1 : 0) +
(1.4 + 0.2 * Math.random()) * (get(cur, x - 1, y) ? 1 : 0) +
(1.1 + 0.2 * Math.random()) * (get(cur, x + 1, y) ? 1 : 0) +
(1.6 - 0.1 * Math.random()) * (get(cur, x - 1, y + 1) ? 1 : 0) +
(1.2 - 0.2 * Math.random()) * (get(cur, x, y + 1) ? 1 : 0) +
(1.0 - 0.1 * Math.random()) * get(cur, x + 1, y + 1 ? 1 : 0);
let e = +(sum <= 6 + (Math.random() - 0.5) * (1 - k / K));
if (
e &&
sum >= 6 - Math.random() * waterInGeneration + 4 * step(110, 0, y)
)
e = 5;
if (
e &&
sum >= 6 - Math.random() * volcanoInGeneration + 6 * step(20, 60, y)
)
e = 4;
set(swp, x, y, e);
}
}
@ -541,14 +549,16 @@ function generate (startX: number, worldSize: [number,number]) {
for (i = 0; i < worldPixelBuf.length; ++i) {
affectColor(worldPixelRawBuf, 4 * i, worldPixelBuf[i]);
}
return ndarray(worldPixelRawBuf, [ worldSize[0], worldSize[1], 4]).transpose(1, 0, 2).step(1, -1, 1);
return ndarray(worldPixelRawBuf, [worldSize[0], worldSize[1], 4])
.transpose(1, 0, 2)
.step(1, -1, 1);
}
const size = [200,200];
const size = [200, 200];
export default class Example extends Component {
state = {
initialState: generate(0, size),
initialState: generate(0, size)
};
render() {
const { forestGrowFactor, fireFactor, waterFactor, speed } = this.props;
@ -571,11 +581,10 @@ export default class Example extends Component {
speed: 60,
forestGrowFactor: 1,
fireFactor: 0,
waterFactor: 0,
waterFactor: 0
};
}
/**
* Game Rule Interactions.
*

View File

@ -1,6 +1,6 @@
//@flow
import React, { Component } from "react";
import { Backbuffer, LinearCopy, Node, Shaders, GLSL } from "gl-react";
import { Uniform, LinearCopy, Node, Shaders, GLSL } from "gl-react";
import { Surface } from "gl-react-dom";
import { Video } from "../video";
import { WebCamSource } from "../webcam";
@ -18,32 +18,36 @@ void main () {
texture2D(back, uv+vec2(0.0, 0.005)),
persistence
).rgb, 1.0);
}` }
}`
}
});
const Persistence = ({ children: t, persistence }) =>
const Persistence = ({ children: t, persistence }) => (
<Node
shader={shaders.Persistence}
backbuffering
uniforms={{ t, back: Backbuffer, persistence }}
/>;
uniforms={{ t, back: Uniform.Backbuffer, persistence }}
/>
);
export default class Example extends Component {
render() {
const {persistence} = this.props;
const { persistence } = this.props;
return (
<Surface width={400} height={300}>
<LinearCopy>
<Persistence persistence={persistence}>{ redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
}</Persistence>
<Persistence persistence={persistence}>
{redraw => (
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
)}
</Persistence>
</LinearCopy>
</Surface>
);
}
static defaultProps = {
persistence: 0.8,
persistence: 0.8
};
}

View File

@ -1,6 +1,6 @@
module.exports=`//@flow
import React, { Component } from "react";
import { Backbuffer, LinearCopy, Node, Shaders, GLSL } from "gl-react";
import { Uniform, LinearCopy, Node, Shaders, GLSL } from "gl-react";
import { Surface } from "gl-react-dom";
import { Video } from "../video";
import { WebCamSource } from "../webcam";
@ -18,33 +18,37 @@ void main () {
texture2D(back, uv+vec2(0.0, 0.005)),
persistence
).rgb, 1.0);
}\` }
}\`
}
});
const Persistence = ({ children: t, persistence }) =>
const Persistence = ({ children: t, persistence }) => (
<Node
shader={shaders.Persistence}
backbuffering
uniforms={{ t, back: Backbuffer, persistence }}
/>;
uniforms={{ t, back: Uniform.Backbuffer, persistence }}
/>
);
export default class Example extends Component {
render() {
const {persistence} = this.props;
const { persistence } = this.props;
return (
<Surface width={400} height={300}>
<LinearCopy>
<Persistence persistence={persistence}>{ redraw =>
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
}</Persistence>
<Persistence persistence={persistence}>
{redraw => (
<Video onFrame={redraw} autoPlay>
<WebCamSource />
</Video>
)}
</Persistence>
</LinearCopy>
</Surface>
);
}
static defaultProps = {
persistence: 0.8,
persistence: 0.8
};
}
`

View File

@ -1,9 +1,11 @@
//@flow
import { TextureLoaderRawObject } from "gl-react";
export default class CanvasTextureLoader extends TextureLoaderRawObject<
HTMLCanvasElement
> {
export default class CanvasTextureLoader
extends TextureLoaderRawObject<HTMLCanvasElement> {
canLoad(input: any) {
return input instanceof HTMLCanvasElement;
}
mapInputSize(canvas: HTMLCanvasElement) {
return [canvas.width, canvas.height];
}
}

View File

@ -69,4 +69,10 @@ export default class ImageTextureLoader extends TextureLoader<string> {
get(input: string) {
return this.textures[input];
}
getSize(input: string) {
const img = this.get(input);
if (img) {
return [img.width, img.height];
}
}
}

View File

@ -1,9 +1,8 @@
//@flow
import { TextureLoaderRawObject } from "gl-react";
export default class VideoTextureLoader extends TextureLoaderRawObject<
HTMLVideoElement
> {
export default class VideoTextureLoader
extends TextureLoaderRawObject<HTMLVideoElement> {
canLoad(input: any) {
return input instanceof HTMLVideoElement;
}
@ -11,4 +10,7 @@ export default class VideoTextureLoader extends TextureLoaderRawObject<
if (video.videoWidth === 0) return null;
return video;
}
mapInputSize(video: HTMLVideoElement) {
return [video.videoWidth, video.videoHeight];
}
}

View File

@ -8,9 +8,8 @@ function hash(obj) {
return JSON.stringify(obj); // FIXME ikr XD
}
export default class ExponentGLObjectTextureLoader extends TextureLoader<
Object
> {
export default class ExponentGLObjectTextureLoader
extends TextureLoader<Object> {
loads: Map<string, DisposablePromise<*>> = new Map();
textures: Map<string, *> = new Map();
dispose() {}
@ -53,4 +52,7 @@ export default class ExponentGLObjectTextureLoader extends TextureLoader<
get(texture: Object) {
return this.textures.get(hash(texture));
}
getSize(texture: Object) {
return null; // FIXME there is currently no way to yield that ( related https://github.com/gre/gl-react/issues/131)
}
}

View File

@ -51,6 +51,7 @@ export const loadAsset = (module: number | { uri: string }): Promise<Asset> =>
export default class ExponentTextureLoader extends TextureLoader<*> {
loads: Map<number | string, DisposablePromise<*>> = new Map();
textures: Map<number | string, *> = new Map();
assetSizes: Map<number | string, *> = new Map();
dispose() {
const { loads } = this;
loads.forEach(d => {
@ -89,6 +90,7 @@ export default class ExponentTextureLoader extends TextureLoader<*> {
asset
);
this.textures.set(key, texture);
this.assetSizes.set(key, [width, height]);
this.loads.delete(key);
return texture;
});
@ -104,4 +106,7 @@ export default class ExponentTextureLoader extends TextureLoader<*> {
get(module: number) {
return this.textures.get(hash(module));
}
getSize(texture: Object) {
return this.assetSizes.get(hash(module));
}
}

View File

@ -57,7 +57,7 @@ public class GLImagesModule extends ReactContextBaseJavaModule {
@Override
protected void onNewResultImpl(@Nullable Bitmap bitmap) {
GLImages.set(glAssetId, bitmap);
cb.invoke(glAssetId);
cb.invoke(glAssetId, bitmap.getWidth(), bitmap.getHeight());
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {

View File

@ -44,7 +44,7 @@ RCT_EXPORT_METHOD(load:(nonnull RCTImageSource *)source
CGColorSpaceRelease(colorSpace);
CGContextRelease(ctx);
GLImagesSet(glAssetId, data, width, height);
cb(@[ @(glAssetId) ]);
cb(@[ @(glAssetId), @(width), @(height) ]);
};
if (error) {
NSLog(@"Image failed to load: %@", error);

View File

@ -4,11 +4,11 @@ import type { DisposablePromise } from "gl-react/lib/helpers/disposable";
import GLImages from "./GLImages";
import type { ImageSource } from "./GLImages";
export default class ImageSourceTextureLoader extends TextureLoader<
ImageSource
> {
export default class ImageSourceTextureLoader
extends TextureLoader<ImageSource> {
loads: Array<DisposablePromise<*>> = [];
textures: Map<number, *> = new Map();
textureSizes: Map<number, *> = new Map();
assetIdForImageSource: Map<ImageSource, number> = new Map();
dispose() {
this.loads.forEach(d => {
@ -32,7 +32,9 @@ export default class ImageSourceTextureLoader extends TextureLoader<
let dispose = () => {
ignored = true;
};
const promise = GLImages.load(imageSource).then((glAssetId: number) => {
const promise = GLImages.load(
imageSource
).then((glAssetId: number, width: number, height: number) => {
if (ignored) return;
let texture;
if (this.textures.has(glAssetId)) {
@ -45,6 +47,7 @@ export default class ImageSourceTextureLoader extends TextureLoader<
glAssetId
});
this.textures.set(glAssetId, texture);
this.textureSizes.set(glAssetId, [width, height]);
}
this.assetIdForImageSource.set(imageSource, glAssetId);
return texture;
@ -57,4 +60,8 @@ export default class ImageSourceTextureLoader extends TextureLoader<
const assetId = this.assetIdForImageSource.get(imageSource);
return assetId && this.textures.get(assetId);
}
getSize(imageSource: ImageSource) {
const assetId = this.assetIdForImageSource.get(imageSource);
return this.textureSizes.get(assetId);
}
}

View File

@ -8,12 +8,23 @@ type NDArray = {
shape: Array<number>,
data: $TypedArray | Array<number>,
stride: Array<number>,
offset: number,
size: Array<number>,
order: Array<number>,
dimension: number,
transpose: (...args: Array<number>) => NDArray,
step: (...args: Array<number>) => NDArray,
lo: (...args: Array<number>) => NDArray,
hi: (...args: Array<number>) => NDArray,
pick: (...args: Array<number>) => *
};
declare module "ndarray" {
declare type NDArray = NDArray;
declare var exports:
(arr: $TypedArray | Array<number>, shape: Array<number>) => NDArray;
declare var exports: (
arr: $TypedArray | Array<number>,
shape?: Array<number>,
stride?: Array<number>,
offset?: number
) => NDArray;
}

View File

@ -1,2 +0,0 @@
//@flow
export default "Backbuffer";

View File

@ -120,7 +120,7 @@ export default class Bus extends Component<{ index: number }, Props, void> {
this.glNode = node;
this.context.glParent.redraw();
}
_removeGLNodeChild() {
_removeGLNodeChild(node: Node) {
this.glNode = null;
}

View File

@ -4,7 +4,7 @@ import React, { Component } from "react";
import PropTypes from "prop-types";
import pool from "typedarray-pool";
import ndarray from "ndarray";
import Backbuffer from "./Backbuffer";
import Uniform from "./Uniform";
import Bus from "./Bus";
import Shaders, {
isShaderIdentifier,
@ -180,6 +180,19 @@ type DefaultProps = {
type AsyncMixed = (redraw?: () => void) => mixed;
const isBackbuffer = (obj: *) => {
if (obj === "Backbuffer") {
console.warn(
'Backbuffer is deprecated, use Uniform.Backbuffer instead: `import {Uniform} from "gl-react"`'
);
return true;
}
return obj === Uniform.Backbuffer;
};
const isTextureSizeGetter = (obj: *) =>
obj && typeof obj === "object" && obj.type === "TextureSize";
const nodeWidthHeight = (
{ width, height }: Props,
{ glSizable }: SurfaceContext
@ -669,8 +682,8 @@ export default class Node extends Component {
this._needsRedraw = true;
}
_addGLNodeChild() {}
_removeGLNodeChild() {}
_addGLNodeChild(node: Node) {}
_removeGLNodeChild(node: Node) {}
_addUniformBus(uniformBus: Bus, uniformName: string, index: number): void {
const array =
@ -828,7 +841,11 @@ export default class Node extends Component {
) => {
let obj = initialObj,
dependency: ?(Node | Bus),
result: ?{ directTexture?: ?WebGLTexture, glNode?: Node };
result: ?{
directTexture?: ?WebGLTexture,
directTextureSize?: ?[number, number],
glNode?: Node
};
if (typeof obj === "function") {
// texture uniform can be a function that resolves the object at draw time.
@ -842,7 +859,7 @@ export default class Node extends Component {
"If you explicitely want to clear a texture, set it to null."
);
}
} else if (obj === Backbuffer) {
} else if (isBackbuffer(obj)) {
// maybe it's backbuffer?
if (!this.drawProps.backbuffering) {
console.warn(
@ -850,7 +867,8 @@ export default class Node extends Component {
);
}
result = {
directTexture: this.getGLOutput()
directTexture: this.getGLOutput(),
directTextureSize: this.getGLSize()
};
} else if (obj instanceof Node) {
// maybe it's a Node?
@ -892,7 +910,10 @@ export default class Node extends Component {
} else {
const t = loader.get(input);
if (t) {
result = { directTexture: t };
result = {
directTexture: t,
directTextureSize: loader.getSize(input)
};
} else {
// otherwise, we will have to load it and postpone the rendering.
const d = loader.load(input);
@ -911,6 +932,14 @@ export default class Node extends Component {
dependency,
textureOptions
});
const getSize = (): ?[number, number] => {
const fallback = [2, 2];
return result
? "directTextureSize" in result
? result.directTextureSize
: result.glNode ? result.glNode.getGLSize() : fallback
: fallback;
};
const prepare = () => {
const texture: WebGLTexture =
(result &&
@ -930,6 +959,7 @@ export default class Node extends Component {
};
return {
getMetaInfo,
getSize,
prepare
};
};
@ -957,6 +987,33 @@ export default class Node extends Component {
getMetaInfo,
prepare
};
} else if (uniformValue === Uniform.Resolution) {
return {
key,
type: uniformType,
value: this.getGLSize()
};
} else if (isTextureSizeGetter(uniformValue)) {
invariant(
uniformValue && typeof uniformValue === "object",
"unexpected textureSize object. Got: %s",
uniformValue
);
const { getSize } = prepareTexture(uniformValue.obj, null, key);
const size = getSize();
if (!size) {
console.warn(
`${nodeName}, uniform ${key}: texture size is undetermined`
);
}
const value = uniformValue.ratio
? size ? size[0] / size[1] : 1
: size || [0, 0];
return {
key,
type: uniformType,
value
};
} else if (Array.isArray(uniformType) && uniformType[0] === "sampler2D") {
let values;
const uniformBus = uniformsBus[key];

View File

@ -30,10 +30,15 @@ export default class TextureLoader<T> {
+canLoad: (input: any) => boolean;
/**
* try to get in sync the texture for a given output. otherwise null.
* try to get in sync the texture for a given input. otherwise null.
*/
+get: (input: T) => ?WebGLTexture;
/**
* try to get in sync the texture size for a given input. otherwise null.
*/
+getSize: (input: T) => ?[number, number];
/**
* load() called if get() was null. it returns a promise and a dispose function.
* It is your responsability to cache the disposable per input.

View File

@ -27,4 +27,7 @@ export default class TextureLoaderNDArray extends TextureLoader<NDArray> {
drawNDArrayTexture(gl, texture, array);
return texture;
}
getSize(array: NDArray) {
return array.shape.slice(0, 2);
}
}

View File

@ -5,6 +5,7 @@ export default class TextureLoaderRawObject<T> extends TextureLoader<T> {
textures: Array<WebGLTexture> = [];
+mapInput: (t: T) => any;
+mapInputSize: (t: T) => ?[number, number];
dispose() {
const { gl } = this;
@ -13,6 +14,12 @@ export default class TextureLoaderRawObject<T> extends TextureLoader<T> {
this.textures = [];
}
getSize(obj: T) {
let texture = this.textureMemoized.get(obj);
if (!texture) return null;
return this.mapInputSize(obj);
}
get(obj: T) {
const { gl } = this;
let texture = this.textureMemoized.get(obj);

View File

@ -0,0 +1,27 @@
//@flow
/**
* A set of Uniform symbols you can pass to a uniform. (recognized and interpreted by Node)
*/
const Uniform = {
/**
* Inject the texture of the previous framebuffer state
*/
Backbuffer: "_Backbuffer_",
/**
* the framebuffer size itself
*/
Resolution: "_Resolution_",
/**
* Inject the size of a given Texture input
* @param {any} obj the texture input object
*/
textureSize: (obj: *) => ({ type: "TextureSize", obj }),
/**
* Inject the width/height ratio of a given Texture input
* @param {any} obj the texture input object
*/
textureSizeRatio: (obj: *) => ({ type: "TextureSize", obj, ratio: true })
};
export default Uniform;

View File

@ -16,9 +16,7 @@ import PropTypes from "prop-types";
* <FooConnected /> // you don't have to provide width, height.
* <FooConnected width={64} height={64} /> // If you do, you override width,height in the context as well, so <Node> is implicitly receiving the new width/height.
*/
const connectSize = (
GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
) =>
const connectSize = (GLComponent: ReactClass<*>) =>
class extends Component {
props: {
width?: number,
@ -54,6 +52,7 @@ const connectSize = (
}
component: ?GLComponent;
getComponent(): ?GLComponent {
// FIXME drop this feature (was used on gl-transitions website...)
return this.component;
}
onRef = (ref: GLComponent) => {
@ -63,7 +62,10 @@ const connectSize = (
const [width, height] = this.getGLSize();
return (
<GLComponent
ref={this.onRef}
ref={
// FIXME drop this feature
typeof GLComponent !== "function" ? this.onRef : undefined
}
{...this.props}
width={width}
height={height}

View File

@ -480,7 +480,7 @@ export default ({
node._addDependent(this);
this.redraw();
}
_removeGLNodeChild(): void {
_removeGLNodeChild(node: Node): void {
this.root = null;
this.redraw();
}

View File

@ -2,9 +2,8 @@
// https://github.com/adamschwartz/log/blob/master/log.js
/* eslint-disable */
const { userAgent, vendor } = typeof navigator !== "undefined"
? navigator
: { userAgent: "", vendor: "" };
const { userAgent, vendor } =
typeof navigator !== "undefined" ? navigator : { userAgent: "", vendor: "" };
var exportedLog,
ffSupport,
@ -22,10 +21,8 @@ var exportedLog,
stringToArgs,
_log;
log = function() {
var args;
args = [];
makeArray(arguments).forEach(function(arg) {
log = function(...args: *) {
args.forEach(function(arg) {
if (typeof arg === "string") {
return (args = args.concat(stringToArgs(arg)));
} else {
@ -35,16 +32,8 @@ log = function() {
return _log.apply(window, args);
};
_log = function() {
return Function.prototype.apply.call(
console.log,
console,
makeArray(arguments)
);
};
makeArray = function(arrayLikeThing) {
return Array.prototype.slice.call(arrayLikeThing);
_log = function(...args: *) {
return Function.prototype.apply.call(console.log, console, args);
};
formats = [
@ -55,7 +44,7 @@ formats = [
},
styles: function() {
return ["font-style: italic", ""];
},
}
},
{
regex: /_([^_]+)_/,
@ -64,7 +53,7 @@ formats = [
},
styles: function() {
return ["font-weight: bold", ""];
},
}
},
{
regex: /`([^`]+)`/,
@ -74,9 +63,9 @@ formats = [
styles: function() {
return [
"background: rgb(255, 255, 219); padding: 1px 5px; border: 1px solid rgba(0, 0, 0, 0.1)",
"",
""
];
},
}
},
{
regex: /\[c=(?:"|')?((?:(?!(?:"|')\]).)*)(?:"|')?\]((?:(?!\[c\]).)*)\[c\]/,
@ -85,10 +74,12 @@ formats = [
},
styles: function(match) {
return [match[1], ""];
},
},
}
}
];
(formats: Array<{ styles: (m: *) => * }>);
hasMatches = function(str) {
var _hasMatches;
_hasMatches = false;
@ -109,7 +100,7 @@ getOrderedMatches = function(str) {
if (match) {
return matches.push({
format: format,
match: match,
match: match
});
}
});

View File

@ -1,5 +1,4 @@
//@flow
import Backbuffer from "./Backbuffer";
import Bus from "./Bus";
import connectSize from "./connectSize";
import createSurface, { list as listSurfaces } from "./createSurface";
@ -11,14 +10,12 @@ import Shaders from "./Shaders";
import TextureLoader from "./TextureLoader";
import TextureLoaderRawObject from "./TextureLoaderRawObject";
import TextureLoaders from "./TextureLoaders";
import Uniform from "./Uniform";
import Visitor from "./Visitor";
import VisitorLogger from "./VisitorLogger";
import Visitors from "./Visitors";
export * from "./legacy";
export {
Backbuffer,
Bus,
connectSize,
createSurface,
@ -31,9 +28,13 @@ export {
TextureLoader,
TextureLoaderRawObject,
TextureLoaders,
Uniform,
Visitor,
VisitorLogger,
Visitors
};
// DEPRECATED
export const Backbuffer = "Backbuffer";
export type { Surface } from "./createSurface";

View File

@ -1,54 +0,0 @@
//@flow
import React from "react";
import connectSize from "./connectSize";
import Bus from "./Bus";
import LinearCopy from "./LinearCopy";
function warn(method, alternative) {
console.warn("gl-react: " + method + " is deprecated. " + alternative);
}
export function createComponent(
renderGLNode: () => React.Element<*>,
staticFields?: Object
) {
warn(
"createComponent(" + String(renderGLNode) + ")",
"You can now just use a normal React Component (or a stateless component function). \n" +
"If you need the contextual {width,height} props, use connectSize() decorator."
);
const C = connectSize(renderGLNode);
Object.assign(C, staticFields);
return C;
}
type UniformProps = {
children?: React.Element<*>,
name: string
};
export class Uniform extends React.Component {
props: UniformProps;
constructor({ name }: UniformProps) {
super();
warn(
"GL.Uniform",
`Please directly use <Node uniforms={{ ${name}: value }}>
You might also need to use <Bus> if you want to reuse content.`
);
}
render() {
let { children } = this.props;
if (!React.isValidElement(this.props.children)) {
children = ( // LinearCopy to the rescue!
<LinearCopy>
{children}
</LinearCopy>
);
}
return (
<Bus uniform={this.props.name}>
{children}
</Bus>
);
}
}

View File

@ -19,7 +19,7 @@ import {
Visitors,
TextureLoader,
TextureLoaders,
Backbuffer,
Uniform,
Bus,
VisitorLogger,
connectSize
@ -42,6 +42,7 @@ import {
red2x2,
white3x3,
yellow3x3,
yellow3x2,
expectToBeCloseToColorArray
} from "./utils";
@ -543,7 +544,7 @@ test("Surface can be resized", () => {
}`
}
});
const renderForSize = (width, height) => (
const renderForSize = (width, height) =>
<Surface
width={width}
height={height}
@ -552,8 +553,7 @@ test("Surface can be resized", () => {
<LinearCopy>
<Node shader={shaders.red} backbuffering />
</LinearCopy>
</Surface>
);
</Surface>;
const inst = create(renderForSize(1, 1));
const surface = inst.getInstance();
inst.update(renderForSize(20, 20));
@ -639,7 +639,9 @@ test("bus example 1", () => {
<Bus ref="bus">
<Node shader={shaders.red} />
</Bus>
<LinearCopy>{() => this.refs.bus}</LinearCopy>
<LinearCopy>
{() => this.refs.bus}
</LinearCopy>
</Surface>
);
}
@ -676,9 +678,13 @@ test("bus example 2", () => {
<Node width={1} height={2} shader={shaders.red} />
</Bus>
<Bus ref="bus2">
<LinearCopy>{() => this.refs.bus1}</LinearCopy>
<LinearCopy>
{() => this.refs.bus1}
</LinearCopy>
</Bus>
<LinearCopy>{() => this.refs.bus2}</LinearCopy>
<LinearCopy>
{() => this.refs.bus2}
</LinearCopy>
</Surface>
);
}
@ -721,7 +727,9 @@ test("bus example 3", () => {
<Bus ref="bus">
<Red />
</Bus>
<LinearCopy>{() => this.refs.bus}</LinearCopy>
<LinearCopy>
{() => this.refs.bus}
</LinearCopy>
</Surface>
);
}
@ -998,13 +1006,12 @@ test("a surface can be captured and resized", () => {
}`
}
});
const render = (w, h) => (
const render = (w, h) =>
<Surface width={w} height={h}>
<LinearCopy>
<Node shader={shaders.helloGL} width={2} height={2} />
</LinearCopy>
</Surface>
);
</Surface>;
const inst = create(render(2, 2));
const surface = inst.getInstance();
expectToBeCloseToColorArray(
@ -1032,7 +1039,7 @@ test("a node can be captured and resized", () => {
}
});
let node;
const render = (w, h) => (
const render = (w, h) =>
<Surface width={20} height={20}>
<LinearCopy>
<Node
@ -1042,8 +1049,7 @@ test("a node can be captured and resized", () => {
height={h}
/>
</LinearCopy>
</Surface>
);
</Surface>;
const inst = create(render(2, 2));
const surface = inst.getInstance();
invariant(node, "node is defined");
@ -1094,12 +1100,11 @@ test("Uniform children redraw=>el function", () => {
>
<NearestCopy>
<LinearCopy>
{redraw => (
{redraw =>
<UpdatingTexture
ref={ref => (updatingTexture = ref)}
redraw={redraw}
/>
)}
/>}
</LinearCopy>
</NearestCopy>
</Surface>
@ -1184,15 +1189,14 @@ test("Bus redraw=>el function", () => {
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
<Bus ref="bus">
{redraw => (
{redraw =>
<UpdatingTexture
initialPixels={yellow3x3}
initialWidth={3}
initialHeight={3}
ref={ref => (updatingTexture = ref)}
redraw={redraw}
/>
)}
/>}
</Bus>
<NearestCopy>
<LinearCopy>
@ -1233,7 +1237,7 @@ test("many Surface updates don't result of many redraws", () => {
});
const visitor = new CountersVisitor();
const wrap = children => (
const wrap = children =>
<Surface
visitor={visitor}
width={2}
@ -1241,11 +1245,9 @@ test("many Surface updates don't result of many redraws", () => {
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
{children}
</Surface>
);
const JustBlue = ({ blue }) => (
<Node shader={shaders.justBlue} uniforms={{ blue }} />
);
</Surface>;
const JustBlue = ({ blue }) =>
<Node shader={shaders.justBlue} uniforms={{ blue }} />;
const inst = create(wrap(<JustBlue blue={0} />));
const surface = inst.getInstance();
@ -1285,7 +1287,7 @@ test("many Surface flush() don't result of extra redraws", () => {
});
const visitor = new CountersVisitor();
const wrap = children => (
const wrap = children =>
<Surface
visitor={visitor}
width={2}
@ -1293,11 +1295,9 @@ test("many Surface flush() don't result of extra redraws", () => {
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
{children}
</Surface>
);
const JustBlue = ({ blue }) => (
<Node shader={shaders.justBlue} uniforms={{ blue }} />
);
</Surface>;
const JustBlue = ({ blue }) =>
<Node shader={shaders.justBlue} uniforms={{ blue }} />;
const inst = create(wrap(<JustBlue blue={0} />));
const surface = inst.getInstance();
@ -1334,15 +1334,16 @@ test("GL Components that implement shouldComponentUpdate shortcut Surface redraw
const visitor = new CountersVisitor();
Visitors.add(visitor);
const wrap = children => (
const wrap = children =>
<Surface
width={2}
height={2}
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
<LinearCopy>{children}</LinearCopy>
</Surface>
);
<LinearCopy>
{children}
</LinearCopy>
</Surface>;
class JustBlue extends React.PureComponent {
render() {
const { blue } = this.props;
@ -1583,7 +1584,7 @@ test("Node `backbuffering`", () => {
}`
}
});
const render = t => (
const render = t =>
<Surface
width={10}
height={10}
@ -1592,8 +1593,7 @@ test("Node `backbuffering`", () => {
<LinearCopy>
<Node shader={shaders.colorShift} uniforms={{ t }} backbuffering />
</LinearCopy>
</Surface>
);
</Surface>;
const inst = create(render(red2x2)); // init with red
const surface = inst.getInstance();
expectToBeCloseToColorArray(
@ -1608,20 +1608,20 @@ test("Node `backbuffering`", () => {
surface.capture(0, 0, 1, 1).data,
new Uint8Array([0, 255, 0, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
surface.flush();
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([0, 0, 255, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
surface.flush();
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([255, 0, 0, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
inst.update(render(Uniform.Backbuffer));
surface.flush();
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
@ -1644,7 +1644,7 @@ test("Node `backbuffering` in `sync`", () => {
}`
}
});
const render = t => (
const render = t =>
<Surface
width={10}
height={10}
@ -1660,8 +1660,7 @@ test("Node `backbuffering` in `sync`", () => {
/>
</LinearCopy>
</LinearCopy>
</Surface>
);
</Surface>;
const inst = create(render(red2x2)); // init with red
const surface = inst.getInstance();
// since node was drawn once, there were a first shift.
@ -1669,18 +1668,18 @@ test("Node `backbuffering` in `sync`", () => {
surface.capture(0, 0, 1, 1).data,
new Uint8Array([0, 255, 0, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([0, 0, 255, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([255, 0, 0, 255])
);
inst.update(render(Backbuffer));
inst.update(render(Backbuffer));
inst.update(render(Uniform.Backbuffer));
inst.update(render(Uniform.Backbuffer));
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([0, 0, 255, 255])
@ -1864,7 +1863,10 @@ test("can be extended with addTextureLoaderClass", async () => {
}
});
const loader = createOneTextureLoader(gl => createNDArrayTexture(gl, red2x2));
const loader = createOneTextureLoader(
gl => createNDArrayTexture(gl, red2x2),
[2, 2]
);
TextureLoaders.add(loader.Loader);
const inst = create(
<Surface
@ -1909,7 +1911,10 @@ test("Surface `preload` prevent to draw anything", async () => {
let onLoadCounter = 0;
const visitor = new CountersVisitor();
const loader = createOneTextureLoader(gl => createNDArrayTexture(gl, red2x2));
const loader = createOneTextureLoader(
gl => createNDArrayTexture(gl, red2x2),
[2, 2]
);
TextureLoaders.add(loader.Loader);
const el = (
<Surface
@ -1947,6 +1952,63 @@ test("Surface `preload` prevent to draw anything", async () => {
TextureLoaders.remove(loader.Loader);
});
test("Uniform.textureSizeRatio allows to send the ratio of a texture in uniform", async () => {
const shaders = Shaders.create({
contain: {
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D t;
uniform float tRatio;
void main() {
vec2 p = uv * vec2(max(1.0, 1.0/tRatio), max(1.0, tRatio)); // "contain" the texture to preserve ratio (without center alignment)
gl_FragColor =
step(0.0, p.x) * step(p.x, 1.0) * // returns 1.0 if x is in [0,1] otherwise 0.0
step(0.0, p.y) * step(p.y, 1.0) * // returns 1.0 if y is in [0,1] otherwise 0.0
texture2D(t, p);
}`
}
});
const loader = createOneTextureLoader(
gl => createNDArrayTexture(gl, yellow3x2),
[3, 2]
);
TextureLoaders.add(loader.Loader);
const el = (
<Surface
width={64}
height={64}
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
<Node
shader={shaders.contain}
uniforms={{
t: loader.textureId,
tRatio: Uniform.textureSizeRatio(loader.textureId)
}}
/>
</Surface>
);
const inst = create(el);
const surface = inst.getInstance();
await loader.resolve();
surface.flush();
expectToBeCloseToColorArray(
surface.capture(0, 0, 1, 1).data,
new Uint8Array([255, 255, 0, 255])
);
expectToBeCloseToColorArray(
surface.capture(0, 32, 1, 1).data,
new Uint8Array([255, 255, 0, 255])
);
expectToBeCloseToColorArray(
surface.capture(0, 63, 1, 1).data,
new Uint8Array([0, 0, 0, 0])
);
inst.unmount();
TextureLoaders.remove(loader.Loader);
});
test("Surface `preload` that fails will trigger onLoadError", async () => {
const shaders = Shaders.create({
helloTexture: {
@ -1962,7 +2024,10 @@ test("Surface `preload` that fails will trigger onLoadError", async () => {
let onLoadCounter = 0;
let onLoadErrorCounter = 0;
const loader = createOneTextureLoader(gl => createNDArrayTexture(gl, red2x2));
const loader = createOneTextureLoader(
gl => createNDArrayTexture(gl, red2x2),
[2, 2]
);
TextureLoaders.add(loader.Loader);
const el = (
<Surface
@ -2112,7 +2177,8 @@ test("testing connectSize() feature", () => {
test("handle context lost nicely", () => {
let surface;
let contextLost = 0, contextRestored = 0;
let contextLost = 0,
contextRestored = 0;
class Example extends React.Component {
render() {
return (
@ -2212,15 +2278,14 @@ void main() {
}
}
const wrap = children => (
const wrap = children =>
<Surface
width={4}
height={4}
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
{children}
</Surface>
);
</Surface>;
const inst = create(wrap(<WeirdSwapping i={0} />));
const surface = inst.getInstance();
@ -2281,7 +2346,12 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
expect(Shaders.get(shaders.helloTexture2)).toBeDefined();
const oldConsole = console;
let groupEnd = 0, log = 0, warn = 0, error = 0, group = 0, groupCollapsed = 0;
let groupEnd = 0,
log = 0,
warn = 0,
error = 0,
group = 0,
groupCollapsed = 0;
console = {
...oldConsole,
@ -2296,11 +2366,12 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
let justBlueNode;
const visitor = new VisitorLogger();
const wrap = children => (
const wrap = children =>
<Surface visitor={visitor} width={2} height={2}>
<LinearCopy>{children}</LinearCopy>
</Surface>
);
<LinearCopy>
{children}
</LinearCopy>
</Surface>;
class JustBlue extends React.PureComponent {
render() {
@ -2334,15 +2405,14 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
);
}
}
const MissingOrInvalidUniforms = () => (
const MissingOrInvalidUniforms = () =>
<Node
ref={ref => {
justBlueNode = ref;
}}
shader={shaders.justBlue}
uniforms={{ nope: [1, 2] }}
/>
);
/>;
class TreeWithZombiesDontBreak extends React.Component {
render() {
@ -2434,7 +2504,13 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
justBlueNode.flush();
justBlueNode.redraw();
justBlueNode.flush();
inst.update(wrap(<NearestCopy><JustBlue blue={0} /></NearestCopy>));
inst.update(
wrap(
<NearestCopy>
<JustBlue blue={0} />
</NearestCopy>
)
);
surface.flush();
inst.update(wrap(<TreeWithZombiesDontBreak />));
surface.flush();
@ -2540,7 +2616,12 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
expect(warn).toBeGreaterThan(0);
warn = 0;
inst.update(
wrap(<Node shader={shaders.helloTexture} uniforms={{ t: Backbuffer }} />)
wrap(
<Node
shader={shaders.helloTexture}
uniforms={{ t: Uniform.Backbuffer }}
/>
)
);
surface.flush();
expect(warn).toBeGreaterThan(0);
@ -2561,7 +2642,9 @@ test("VisitorLogger + bunch of funky extreme tests", () => {
<Bus ref="bus">
<JustBlue blue={0.2} />
</Bus>
<LinearCopy>{() => this.refs.bus}</LinearCopy>
<LinearCopy>
{() => this.refs.bus}
</LinearCopy>
</Surface>
);
}

View File

@ -9,18 +9,16 @@ import {
Visitor,
TextureLoader,
TextureLoaders,
Backbuffer,
Uniform,
Bus,
VisitorLogger,
connectSize,
connectSize
} from "gl-react";
import {
Surface,
} from "gl-react-headless";
import { Surface } from "gl-react-headless";
const shaders = Shaders.create({
a: {
frag: GLSL`...`,
frag: GLSL`...`
},
b: {
frag: "..."
@ -31,7 +29,7 @@ class A extends React.Component {
surface: ?Surface;
node: ?Node;
doThings() {
const {surface, node} = this;
const { surface, node } = this;
if (surface && node) {
surface.redraw();
node.redraw();
@ -43,56 +41,58 @@ class A extends React.Component {
}
render() {
return (
<Surface ref={ref => this.surface=ref} width={100} height={200}>
<Bus ref="foo">
<Node shader={shaders.b} />
</Bus>
<Bus ref="bar">
<canvas />
</Bus>
<LinearCopy>
<Node
ref={ref => this.node=ref}
width={1}
height={1}
shader={shaders.a}
backbuffering
uniformsOptions={{
foo: { interpolation: "nearest" },
b: { interpolation: "linear" },
}}
uniforms={{
foo: () => this.refs.foo,
bar: () => this.refs.bar,
b: Backbuffer,
}}
/>
</LinearCopy>
</Surface>
<Surface ref={ref => (this.surface = ref)} width={100} height={200}>
<Bus ref="foo">
<Node shader={shaders.b} />
</Bus>
<Bus ref="bar">
<canvas />
</Bus>
<LinearCopy>
<Node
ref={ref => (this.node = ref)}
width={1}
height={1}
shader={shaders.a}
backbuffering
uniformsOptions={{
foo: { interpolation: "nearest" },
b: { interpolation: "linear" }
}}
uniforms={{
foo: () => this.refs.foo,
bar: () => this.refs.bar,
b: Uniform.Backbuffer,
bs: Uniform.textureSize(""),
br: Uniform.textureSizeRatio("")
}}
/>
</LinearCopy>
</Surface>
);
}
}
const N = connectSize(({ width, height }) =>
<Node
sync
clear={null}
width={width}
height={height}
blendFunc={{ src: "one", dst: "zero" }}
shader={shaders.b}
/>);
<Node
sync
clear={null}
width={width}
height={height}
blendFunc={{ src: "one", dst: "zero" }}
shader={shaders.b}
/>
);
const B = () =>
<Surface
width={100}
height={200}
visitor={new VisitorLogger()}
preload={[ "https://i.imgur.com/5EOyTDQ.jpg" ]}
preload={["https://i.imgur.com/5EOyTDQ.jpg"]}
style={{ margin: 10 }}
>
<NearestCopy>
<N width={10} height={10} />
</NearestCopy>
</Surface>
;
</Surface>;

View File

@ -12,11 +12,9 @@ import {
Backbuffer,
Bus,
VisitorLogger,
connectSize,
connectSize
} from "gl-react";
import {
Surface,
} from "gl-react-headless";
import { Surface } from "gl-react-headless";
<Node />;
<Surface />;
@ -32,18 +30,18 @@ import {
const shaders = Shaders.create({
valid: {
frag: GLSL`...`,
frag: GLSL`...`
},
a: null,
b: {},
c: { frag: true },
c: { frag: true }
});
class A extends React.Component {
surface: ?Surface;
node: ?Node;
doThings() {
const {surface, node} = this;
const { surface, node } = this;
if (surface && node) {
surface.nope();
node.nope();
@ -51,17 +49,14 @@ class A extends React.Component {
}
render() {
return (
<Surface ref={ref => this.surface=ref} notexists>
<Bus ref="o" notexists>
<Node />
</Bus>
<LinearCopy notexists>
<Node
shaders={shaders.valid}
notexists
/>
</LinearCopy>
</Surface>
<Surface ref={ref => (this.surface = ref)} notexists>
<Bus ref="o" notexists>
<Node />
</Bus>
<LinearCopy notexists>
<Node shaders={shaders.valid} notexists />
</LinearCopy>
</Surface>
);
}
}
@ -69,19 +64,19 @@ class A extends React.Component {
connectSize();
const N = connectSize(() =>
// these are all wrong props
<Node
sync={1}
clear={42}
width={false}
height={false}
blendFunc={{
src: "nope",
interpolation: "interpolation_nope",
wrap: "wrap_nope",
}}
preload={false}
visitor={false}
shader={false}
/>
// these are all wrong props
<Node
sync={1}
clear={42}
width={false}
height={false}
blendFunc={{
src: "nope",
interpolation: "interpolation_nope",
wrap: "wrap_nope"
}}
preload={false}
visitor={false}
shader={false}
/>
);

View File

@ -1,25 +1,25 @@
../all.test.js:2496
../all.test.js:2572
v----
2496: <Node
2497: shader={shaders.helloTexture}
2498: uniformsOptions={{ t: { interpolation: "nope" } }}
2499: uniforms={{ t: <JustBlue blue={1} /> }}
2500: />
2572: <Node
2573: shader={shaders.helloTexture}
2574: uniformsOptions={{ t: { interpolation: "nope" } }}
2575: uniforms={{ t: <JustBlue blue={1} /> }}
2576: />
-^ props of React element `Node`
2498: uniformsOptions={{ t: { interpolation: "nope" } }}
2574: uniformsOptions={{ t: { interpolation: "nope" } }}
^^^^^^ string. This type is incompatible with
65: interpolation: Interpolation,
^^^^^^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:65
../all.test.js:2508
../all.test.js:2584
v----
2508: <Node
2509: shader={shaders.helloTexture}
2510: uniformsOptions={{ t: { wrap: "nope" } }}
2511: uniforms={{ t: <JustBlue blue={1} /> }}
2512: />
2584: <Node
2585: shader={shaders.helloTexture}
2586: uniformsOptions={{ t: { wrap: "nope" } }}
2587: uniforms={{ t: <JustBlue blue={1} /> }}
2588: />
-^ props of React element `Node`
2510: uniformsOptions={{ t: { wrap: "nope" } }}
2586: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: tuple type | WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
@ -27,7 +27,7 @@
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2510: uniformsOptions={{ t: { wrap: "nope" } }}
2586: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
@ -35,20 +35,20 @@
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^ WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2510: uniformsOptions={{ t: { wrap: "nope" } }}
2586: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66
../all.test.js:2520
../all.test.js:2596
v----
2520: <Node
2521: shader={shaders.helloTexture}
2522: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2523: uniforms={{ t: <JustBlue blue={1} /> }}
2524: />
2596: <Node
2597: shader={shaders.helloTexture}
2598: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2599: uniforms={{ t: <JustBlue blue={1} /> }}
2600: />
-^ props of React element `Node`
2522: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2598: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^^^^^^^^^^^ array literal. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: tuple type | WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
@ -56,7 +56,7 @@
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2522: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2598: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66
@ -64,611 +64,373 @@
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^ WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2522: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2598: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^^^^^^^^^^^ array literal. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66
../all.test.js:2532
../all.test.js:2608
v----
2532: <Node
2533: blendFunc="nope"
2534: shader={shaders.helloTexture}
2535: uniforms={{ t: <JustBlue blue={1} /> }}
2536: />
2608: <Node
2609: blendFunc="nope"
2610: shader={shaders.helloTexture}
2611: uniforms={{ t: <JustBlue blue={1} /> }}
2612: />
-^ props of React element `Node`
2533: blendFunc="nope"
2609: blendFunc="nope"
^^^^^^ string. Inexact type is incompatible with exact type
177: blendFunc: BlendFuncSrcDst,
^^^^^^^^^^^^^^^ exact type: object type. See: ../node_modules/gl-react/lib/Node.js.flow:177
incorrect.js:21
21: <Node />;
incorrect.js:19
19: <Node />;
^^^^^^^^ React element `Node`
380: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:380
21: <Node />;
393: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:393
19: <Node />;
^^^^^^^^ props of React element `Node`
incorrect.js:27
27: <Node nope />;
incorrect.js:25
25: <Node nope />;
^^^^^^^^^^^^^ React element `Node`
27: <Node nope />;
25: <Node nope />;
^^^^^^^^^^^^^ property `nope`. Property not found in
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
incorrect.js:27
27: <Node nope />;
incorrect.js:25
25: <Node nope />;
^^^^^^^^^^^^^ React element `Node`
380: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:380
27: <Node nope />;
393: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:393
25: <Node nope />;
^^^^^^^^^^^^^ props of React element `Node`
incorrect.js:29
29: <LinearCopy nope />;
incorrect.js:27
27: <LinearCopy nope />;
^^^^^^^^^^^^^^^^^^^ React element `LinearCopy`
29: <LinearCopy nope />;
27: <LinearCopy nope />;
^^^^^^^^^^^^^^^^^^^ property `nope`. Property not found in
15: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/LinearCopy.js.flow:15
incorrect.js:30
30: <NearestCopy nope />;
incorrect.js:28
28: <NearestCopy nope />;
^^^^^^^^^^^^^^^^^^^^ React element `NearestCopy`
30: <NearestCopy nope />;
28: <NearestCopy nope />;
^^^^^^^^^^^^^^^^^^^^ property `nope`. Property not found in
15: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/NearestCopy.js.flow:15
incorrect.js:31
31: <Bus nope />;
incorrect.js:29
29: <Bus nope />;
^^^^^^^^^^^^ React element `Bus`
31: <Bus nope />;
29: <Bus nope />;
^^^^^^^^^^^^ property `nope`. Property not found in
45: export default class Bus extends Component<{ index: number }, Props, void> {
^^^^^ object type. See: ../node_modules/gl-react/lib/Bus.js.flow:45
incorrect.js:33
incorrect.js:31
v---------------
33: const shaders = Shaders.create({
34: valid: {
35: frag: GLSL`...`,
31: const shaders = Shaders.create({
32: valid: {
33: frag: GLSL`...`
...:
40: });
38: });
-^ call of method `create`
37: a: null,
35: a: null,
^^^^ null. Inexact type is incompatible with exact type
45: [key: string]: ShaderDefinition
^^^^^^^^^^^^^^^^ exact type: object type. See: ../node_modules/gl-react/lib/Shaders.js.flow:45
incorrect.js:33
incorrect.js:31
v---------------
33: const shaders = Shaders.create({
34: valid: {
35: frag: GLSL`...`,
31: const shaders = Shaders.create({
32: valid: {
33: frag: GLSL`...`
...:
40: });
38: });
-^ call of method `create`
45: [key: string]: ShaderDefinition
^^^^^^^^^^^^^^^^ property `frag`. Property not found in. See: ../node_modules/gl-react/lib/Shaders.js.flow:45
38: b: {},
36: b: {},
^^ object literal
incorrect.js:39
39: c: { frag: true },
incorrect.js:37
37: c: { frag: true }
^^^^^^^^^^^^^^ object literal. This type is incompatible with
45: [key: string]: ShaderDefinition
^^^^^^^^^^^^^^^^ object type. See: ../node_modules/gl-react/lib/Shaders.js.flow:45
Property `frag` is incompatible:
39: c: { frag: true },
37: c: { frag: true }
^^^^ boolean. This type is incompatible with
16: frag: GLSLCode
^^^^^^^^ string. See: ../node_modules/gl-react/lib/Shaders.js.flow:16
incorrect.js:48
48: surface.nope();
incorrect.js:46
46: surface.nope();
^^^^ property `nope`. Property not found in
48: surface.nope();
46: surface.nope();
^^^^^^^ ISurface
incorrect.js:49
49: node.nope();
incorrect.js:47
47: node.nope();
^^^^ property `nope`. Property not found in
49: node.nope();
47: node.nope();
^^^^ Node
incorrect.js:55
55: <Bus ref="o" notexists>
^^^^^^^^^^^^^^^^^^^^^^^ React element `Bus`
55: <Bus ref="o" notexists>
^^^^^^^^^^^^^^^^^^^^^^^ property `notexists`. Property not found in
incorrect.js:53
53: <Bus ref="o" notexists>
^^^^^^^^^^^^^^^^^^^^^^^ React element `Bus`
53: <Bus ref="o" notexists>
^^^^^^^^^^^^^^^^^^^^^^^ property `notexists`. Property not found in
45: export default class Bus extends Component<{ index: number }, Props, void> {
^^^^^ object type. See: ../node_modules/gl-react/lib/Bus.js.flow:45
incorrect.js:56
56: <Node />
^^^^^^^^ React element `Node`
380: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:380
56: <Node />
^^^^^^^^ props of React element `Node`
incorrect.js:54
54: <Node />
^^^^^^^^ React element `Node`
393: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:393
54: <Node />
^^^^^^^^ props of React element `Node`
incorrect.js:58
58: <LinearCopy notexists>
^^^^^^^^^^^^^^^^^^^^^^ React element `LinearCopy`
58: <LinearCopy notexists>
^^^^^^^^^^^^^^^^^^^^^^ property `notexists`. Property not found in
incorrect.js:56
56: <LinearCopy notexists>
^^^^^^^^^^^^^^^^^^^^^^ React element `LinearCopy`
56: <LinearCopy notexists>
^^^^^^^^^^^^^^^^^^^^^^ property `notexists`. Property not found in
15: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/LinearCopy.js.flow:15
incorrect.js:59
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ React element `Node`
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ property `notexists`. Property not found in
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
incorrect.js:57
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element `Node`
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ property `notexists`. Property not found in
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
incorrect.js:59
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ React element `Node`
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ property `shaders`. Property not found in
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
incorrect.js:57
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element `Node`
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ property `shaders`. Property not found in
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
incorrect.js:59
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ React element `Node`
380: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:380
v----
59: <Node
60: shaders={shaders.valid}
61: notexists
62: />
-^ props of React element `Node`
incorrect.js:57
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element `Node`
393: props: Props;
^^^^^ property `shader`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:393
57: <Node shaders={shaders.valid} notexists />
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ props of React element `Node`
incorrect.js:69
69: connectSize();
incorrect.js:64
64: connectSize();
^^^^^^^^^^^^^ function call
69: connectSize();
64: connectSize();
^^^^^^^^^^^^^ undefined (too few arguments, expected default/rest parameters). This type is incompatible with
20: GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: type application of identifier `ReactClass` | function type. See: ../node_modules/gl-react/lib/connectSize.js.flow:20
Member 1:
20: GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
^^^^^^^^^^^^^ type application of identifier `ReactClass`. See: ../node_modules/gl-react/lib/connectSize.js.flow:20
Error:
69: connectSize();
^^^^^^^^^^^^^ undefined (too few arguments, expected default/rest parameters). This type is incompatible with
20: GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
^^^^^^^^^^^^^ class type: C. See: ../node_modules/gl-react/lib/connectSize.js.flow:20
Member 2:
20: GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See: ../node_modules/gl-react/lib/connectSize.js.flow:20
Error:
69: connectSize();
^^^^^^^^^^^^^ undefined (too few arguments, expected default/rest parameters). This type is incompatible with
20: GLComponent: ReactClass<*> | ((props: any) => React.Element<*>)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See: ../node_modules/gl-react/lib/connectSize.js.flow:20
19: const connectSize = (GLComponent: ReactClass<*>) =>
^^^^^^^^^^^^^ class type: C. See: ../node_modules/gl-react/lib/connectSize.js.flow:19
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ React element `Node`
v----
73: <Node
74: sync={1}
75: clear={42}
81: />
-^ React element `Node`
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ property `preload`. Property not found in
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
81: />
-^ property `preload`. Property not found in
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ React element `Node`
v----
73: <Node
74: sync={1}
75: clear={42}
81: />
-^ React element `Node`
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ property `visitor`. Property not found in
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
81: />
-^ property `visitor`. Property not found in
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ React element `Node`
85: shader={false}
^^^^^ boolean. This type is incompatible with
81: />
-^ React element `Node`
80: shader={false}
^^^^^ boolean. This type is incompatible with
160: shader: ShaderIdentifier | ShaderDefinition,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: ShaderIdentifier | ShaderDefinition. See: ../node_modules/gl-react/lib/Node.js.flow:160
Member 1:
160: shader: ShaderIdentifier | ShaderDefinition,
^^^^^^^^^^^^^^^^ ShaderIdentifier. See: ../node_modules/gl-react/lib/Node.js.flow:160
Error:
85: shader={false}
^^^^^ boolean. This type is incompatible with
80: shader={false}
^^^^^ boolean. This type is incompatible with
160: shader: ShaderIdentifier | ShaderDefinition,
^^^^^^^^^^^^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:160
Member 2:
160: shader: ShaderIdentifier | ShaderDefinition,
^^^^^^^^^^^^^^^^ ShaderDefinition. See: ../node_modules/gl-react/lib/Node.js.flow:160
Error:
85: shader={false}
^^^^^ boolean. Inexact type is incompatible with exact type
80: shader={false}
^^^^^ boolean. Inexact type is incompatible with exact type
160: shader: ShaderIdentifier | ShaderDefinition,
^^^^^^^^^^^^^^^^ exact type: object type. See: ../node_modules/gl-react/lib/Node.js.flow:160
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`. This type is incompatible with
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
81: />
-^ props of React element `Node`. This type is incompatible with
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
Property `height` is incompatible:
77: height={false}
^^^^^ boolean. This type is incompatible with
72: height={false}
^^^^^ boolean. This type is incompatible with
165: height?: number,
^^^^^^ number. See: ../node_modules/gl-react/lib/Node.js.flow:165
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`. This type is incompatible with
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
81: />
-^ props of React element `Node`. This type is incompatible with
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
Property `sync` is incompatible:
74: sync={1}
^ number. This type is incompatible with
69: sync={1}
^ number. This type is incompatible with
163: sync?: boolean,
^^^^^^^ boolean. See: ../node_modules/gl-react/lib/Node.js.flow:163
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`. This type is incompatible with
380: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:380
81: />
-^ props of React element `Node`. This type is incompatible with
393: props: Props;
^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:393
Property `width` is incompatible:
76: width={false}
^^^^^ boolean. This type is incompatible with
71: width={false}
^^^^^ boolean. This type is incompatible with
164: width?: number,
^^^^^^ number. See: ../node_modules/gl-react/lib/Node.js.flow:164
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`
75: clear={42}
^^ number. Inexact type is incompatible with exact type
81: />
-^ props of React element `Node`
70: clear={42}
^^ number. Inexact type is incompatible with exact type
178: clear: ?Clear
^^^^^ exact type: object type. See: ../node_modules/gl-react/lib/Node.js.flow:178
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`
v
78: blendFunc={{
79: src: "nope",
80: interpolation: "interpolation_nope",
81: wrap: "wrap_nope",
82: }}
^ property `interpolation`. Property not found in
81: />
-^ props of React element `Node`
v
73: blendFunc={{
74: src: "nope",
75: interpolation: "interpolation_nope",
76: wrap: "wrap_nope"
77: }}
^ property `interpolation`. Property not found in
177: blendFunc: BlendFuncSrcDst,
^^^^^^^^^^^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:177
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`
v
78: blendFunc={{
79: src: "nope",
80: interpolation: "interpolation_nope",
81: wrap: "wrap_nope",
82: }}
^ property `wrap`. Property not found in
81: />
-^ props of React element `Node`
v
73: blendFunc={{
74: src: "nope",
75: interpolation: "interpolation_nope",
76: wrap: "wrap_nope"
77: }}
^ property `wrap`. Property not found in
177: blendFunc: BlendFuncSrcDst,
^^^^^^^^^^^^^^^ object type. See: ../node_modules/gl-react/lib/Node.js.flow:177
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`
79: src: "nope",
^^^^^^ property `nope`. Property not found in
81: />
-^ props of React element `Node`
74: src: "nope",
^^^^^^ property `nope`. Property not found in
95: src: BlendFunc,
^^^^^^^^^ object literal. See: ../node_modules/gl-react/lib/Node.js.flow:95
incorrect.js:73
v----
73: <Node
74: sync={1}
75: clear={42}
incorrect.js:68
v----
68: <Node
69: sync={1}
70: clear={42}
...:
86: />
-^ props of React element `Node`
81: />
-^ props of React element `Node`
177: blendFunc: BlendFuncSrcDst,
^^^^^^^^^^^^^^^ property `dst`. Property not found in. See: ../node_modules/gl-react/lib/Node.js.flow:177
v
78: blendFunc={{
79: src: "nope",
80: interpolation: "interpolation_nope",
81: wrap: "wrap_nope",
82: }}
^ object literal
v
73: blendFunc={{
74: src: "nope",
75: interpolation: "interpolation_nope",
76: wrap: "wrap_nope"
77: }}
^ object literal
../node_modules/gl-react/lib/Node.js.flow:431
431: this.context.glParent._addGLNodeChild(this);
^^^^ unused function argument
672: _addGLNodeChild() {}
^^^^^^^^^^^^^^^^^^^^ function expects no arguments
../node_modules/gl-react/lib/Node.js.flow:443
443: this.context.glParent._removeGLNodeChild(this);
^^^^ unused function argument
v---------------------
123: _removeGLNodeChild() {
124: this.glNode = null;
125: }
^ function expects no arguments. See: ../node_modules/gl-react/lib/Bus.js.flow:123
../node_modules/gl-react/lib/Node.js.flow:443
443: this.context.glParent._removeGLNodeChild(this);
^^^^ unused function argument
673: _removeGLNodeChild() {}
^^^^^^^^^^^^^^^^^^^^^^^ function expects no arguments
../node_modules/gl-react/lib/VisitorLogger.js.flow:25
25: log(surface.getGLName() + " _context acquired_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:25
25: log(surface.getGLName() + " _context acquired_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:27
27: log(surface.getGLName() + " _context lost_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:27
27: log(surface.getGLName() + " _context lost_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:35
35: log("_size_ `" + width + "`x`" + height + "`");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:35
35: log("_size_ `" + width + "`x`" + height + "`");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:51
v-----------------
51: node.getGLName() +
52: " redraw _skipped_: " +
53: (!node.context.glSurface.gl
54: ? "no gl context available!"
55: : !node._needsRedraw ? "no need to redraw" : "")
-----------------------------------------------^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:51
v-----------------
51: node.getGLName() +
52: " redraw _skipped_: " +
53: (!node.context.glSurface.gl
54: ? "no gl context available!"
55: : !node._needsRedraw ? "no need to redraw" : "")
-----------------------------------------------^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:86
v-----------
86: "_size_ `" +
87: w +
88: "`x`" +
...:
96: "`"
--^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:86
v-----------
86: "_size_ `" +
87: w +
88: "`x`" +
...:
96: "`"
--^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:98
98: log("_" + preparedUniforms.length + " uniforms:_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:98
98: log("_" + preparedUniforms.length + " uniforms:_");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../node_modules/gl-react/lib/VisitorLogger.js.flow:113
v------------------------------
113: `${spaces}*${type === "UNKNOWN"
114: ? "[c='color:red']UNKNOWN[c]"
115: : type}* _${key}_ = ${values}`,
-----------------------------^ unused function argument
v-----------
25: log = function() {
26: var args;
27: args = [];
...:
36: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:25
../node_modules/gl-react/lib/VisitorLogger.js.flow:113
v------------------------------
113: `${spaces}*${type === "UNKNOWN"
114: ? "[c='color:red']UNKNOWN[c]"
115: : type}* _${key}_ = ${values}`,
-----------------------------^ unused function argument
v-----------
38: _log = function() {
39: return Function.prototype.apply.call(
40: console.log,
...:
44: };
^ function expects no arguments. See: ../node_modules/gl-react/lib/helpers/log.js.flow:38
../utils.js:42
42: expect(actual).toBeInstanceOf(Uint8Array);
^^^^^^ identifier `expect`. Could not resolve name
... 24 more errors (only 50 out of 74 errors displayed)
To see all errors, re-run Flow with --show-all-errors
Found 34 errors

View File

@ -249,8 +249,40 @@ export const yellow3x3 = ndarray(
]),
[3, 3, 4]
);
export const yellow3x2 = ndarray(
new Uint8Array([
255,
255,
0,
255,
255,
255,
0,
255,
255,
255,
0,
255,
255,
255,
0,
255,
255,
255,
0,
255,
255,
255,
0,
255
]),
[3, 2, 4]
);
export function createOneTextureLoader(makeTexture: (gl: any) => WebGLTexture) {
export function createOneTextureLoader(
makeTexture: (gl: any) => WebGLTexture,
size: [number, number]
) {
const textureId = Symbol("one-texture");
const counters = {
constructor: 0,
@ -287,6 +319,9 @@ export function createOneTextureLoader(makeTexture: (gl: any) => WebGLTexture) {
++counters.get;
return this.texture;
}
getSize() {
return size;
}
load() {
++counters.load;
const promise = d.promise.then(() => {
@ -332,6 +367,9 @@ class FakeTextureLoader extends TextureLoader<FakeTexture> {
canLoad(input: any) {
return input instanceof FakeTexture;
}
getSize(ft: FakeTexture) {
return [ft.width, ft.height];
}
get(ft: FakeTexture) {
const array = ft.getPixels();
if (array) {