diff --git a/cookbook-rn/exp.json b/cookbook-rn/exp.json
index 00fb47b..0db86a3 100755
--- a/cookbook-rn/exp.json
+++ b/cookbook-rn/exp.json
@@ -1,8 +1,8 @@
{
- "name": "glrn-ex",
- "description": "An empty new project",
- "slug": "glrn-ex",
- "sdkVersion": "11.0.3",
+ "name": "glrn-cookbook",
+ "description": "GL React Native Cookbook",
+ "slug": "glrn-cookbook",
+ "sdkVersion": "12.0.0",
"version": "1.0.0",
"orientation": "portrait",
"primaryColor": "#cccccc",
diff --git a/cookbook-rn/main.js b/cookbook-rn/main.js
index 14e672e..857fe66 100755
--- a/cookbook-rn/main.js
+++ b/cookbook-rn/main.js
@@ -1,32 +1,4 @@
+import "exponent";
import Exponent from "exponent";
-import React from "react";
-import {
- StyleSheet,
- Text,
- View,
-} from "react-native";
-import HelloGL from "./HelloGL";
-import HelloTexture from "./HelloTexture";
-
-class App extends React.Component {
- render() {
- return (
-
-
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: "#fff",
- alignItems: "center",
- justifyContent: "center",
- flexDirection: "column",
- },
-});
-
+import App from "./src";
Exponent.registerRootComponent(App);
diff --git a/cookbook-rn/package.json b/cookbook-rn/package.json
old mode 100755
new mode 100644
index 832e7f6..54be233
--- a/cookbook-rn/package.json
+++ b/cookbook-rn/package.json
@@ -1,15 +1,23 @@
{
- "name": "glrn-ex",
+ "name": "glrn-cookbook",
"version": "0.0.0",
- "description": "Hello Exponent!",
- "author": null,
+ "description": "GL React Native cookbook",
+ "author": "Gaëtan Renaudeau",
"private": true,
"main": "main.js",
"dependencies": {
- "exponent": "^11.0.3-rc.1",
- "gl-react": "file:../packages/gl-react",
- "gl-react-native": "file:../packages/gl-react-native",
+ "@exponent/ex-navigation": "^2.3.0",
+ "exponent": "^12.0.5",
+ "gl-react": "^3.0.0-alpha1",
+ "gl-react-native": "^3.0.0-alpha1",
+ "glsl-transitions": "^2016.12.26",
+ "ndarray": "^1.0.18",
+ "raf": "^3.3.0",
"react": "~15.3.2",
- "react-native": "github:exponentjs/react-native#sdk-11.0.2"
+ "react-motion": "^0.4.7",
+ "react-native": "github:exponentjs/react-native#sdk-12.0.0"
+ },
+ "scripts": {
+ "generate-examples": "cd src/examples; ./gen.sh 1> index.js"
}
}
diff --git a/cookbook-rn/src/0BJobQo.jpg b/cookbook-rn/src/0BJobQo.jpg
new file mode 100644
index 0000000..99504be
Binary files /dev/null and b/cookbook-rn/src/0BJobQo.jpg differ
diff --git a/cookbook-rn/src/0PkQEk1.jpg b/cookbook-rn/src/0PkQEk1.jpg
new file mode 100644
index 0000000..70dd467
Binary files /dev/null and b/cookbook-rn/src/0PkQEk1.jpg differ
diff --git a/cookbook-rn/src/0bUSEBX.jpg b/cookbook-rn/src/0bUSEBX.jpg
new file mode 100644
index 0000000..9e04401
Binary files /dev/null and b/cookbook-rn/src/0bUSEBX.jpg differ
diff --git a/cookbook-rn/src/2VP5osy.jpg b/cookbook-rn/src/2VP5osy.jpg
new file mode 100644
index 0000000..58b7dce
Binary files /dev/null and b/cookbook-rn/src/2VP5osy.jpg differ
diff --git a/cookbook-rn/5EOyTDQ.jpg b/cookbook-rn/src/5EOyTDQ.jpg
similarity index 100%
rename from cookbook-rn/5EOyTDQ.jpg
rename to cookbook-rn/src/5EOyTDQ.jpg
diff --git a/cookbook-rn/src/CKlmtPs.jpg b/cookbook-rn/src/CKlmtPs.jpg
new file mode 100644
index 0000000..0526a41
Binary files /dev/null and b/cookbook-rn/src/CKlmtPs.jpg differ
diff --git a/cookbook-rn/src/G2Whuq3.jpg b/cookbook-rn/src/G2Whuq3.jpg
new file mode 100644
index 0000000..5167d6b
Binary files /dev/null and b/cookbook-rn/src/G2Whuq3.jpg differ
diff --git a/cookbook-rn/src/GQo1KWq.jpg b/cookbook-rn/src/GQo1KWq.jpg
new file mode 100644
index 0000000..7cb1fff
Binary files /dev/null and b/cookbook-rn/src/GQo1KWq.jpg differ
diff --git a/cookbook-rn/src/HOC/respondToTouchPosition.js b/cookbook-rn/src/HOC/respondToTouchPosition.js
new file mode 100644
index 0000000..2f41401
--- /dev/null
+++ b/cookbook-rn/src/HOC/respondToTouchPosition.js
@@ -0,0 +1,76 @@
+//@flow
+import React, { Component } from "react";
+import { PanResponder, View } from "react-native";
+import hoistNonReactStatics from "hoist-non-react-statics";
+
+type Pos = { x: number, y: number };
+type State = { touching: boolean, touchPosition: Pos };
+
+export default (Comp: ReactClass<*>, {
+ initialPosition = { x: 0.5, y: 0.5 }
+}: { initialPosition: Pos } = {}) => {
+ class TouchPositionResponding extends Component {
+ state: State = {
+ touching: false,
+ touchPosition: initialPosition,
+ };
+ initialContainerPos: [number, number];
+ initialDragPos: [number, number];
+ size: [number, number];
+ panResponder = PanResponder.create({
+ onStartShouldSetPanResponder: () => true,
+ onStartShouldSetPanResponderCapture: () => true,
+ onMoveShouldSetPanResponder: () => true,
+ onMoveShouldSetPanResponderCapture: () => true,
+ onPanResponderGrant: (evt) => {
+ const { pageX, pageY } = evt.nativeEvent;
+ this.initialDragPos = [ pageX, pageY ];
+ this.refs.root.measure((x, y, w, h, initialPageX, initialPageY) => {
+ this.initialContainerPos = [ initialPageX, initialPageY ];
+ this.size = [ w, h ];
+ this.setState({
+ touching: true,
+ touchPosition: {
+ x: (pageX - initialPageX) / w,
+ y: 1 - (pageY - initialPageY) / h,
+ }
+ });
+ });
+ },
+ onPanResponderMove: (evt, gestureState) => {
+ const [ pageX, pageY ] = this.initialDragPos;
+ const [ initialPageX, initialPageY ] = this.initialContainerPos;
+ const { dx, dy } = gestureState;
+ const [ w, h ] = this.size;
+ this.setState({
+ touchPosition: {
+ x: (pageX + dx - initialPageX) / w,
+ y: 1 - (pageY + dy - initialPageY) / h,
+ }
+ });
+ },
+ onPanResponderTerminationRequest: () => true,
+ onPanResponderRelease: () => this._onEnd(),
+ onPanResponderTerminate: () => this._onEnd(),
+ onShouldBlockNativeResponder: () => true,
+ });
+ _onEnd = () => {
+ if (this.state.touching) {
+ this.setState({
+ touching: false,
+ });
+ }
+ };
+ render() {
+ return (
+
+
+
+ );
+ }
+ }
+
+ hoistNonReactStatics(TouchPositionResponding, Comp);
+
+ return TouchPositionResponding;
+};
diff --git a/cookbook-rn/src/HOC/timeLoop.js b/cookbook-rn/src/HOC/timeLoop.js
new file mode 100644
index 0000000..8db07f5
--- /dev/null
+++ b/cookbook-rn/src/HOC/timeLoop.js
@@ -0,0 +1,50 @@
+//@flow
+import React, { PureComponent } from "react";
+import raf from "raf";
+import hoistNonReactStatics from "hoist-non-react-statics";
+
+// NB this is only an utility for the examples
+export default (
+ C: ReactClass<*>,
+ { refreshRate = 60 }: { refreshRate?: number } = {}
+): ReactClass<*> => {
+ class TL extends PureComponent {
+ static displayName = `timeLoop(${C.displayName||C.name||""})`;
+ state: { time: number };
+ state = {
+ time: 0,
+ tick: 0,
+ };
+ _r: any;
+ componentDidMount() {
+ let startTime: number, lastTime: number;
+ let interval = 1000 / refreshRate;
+ lastTime = -interval;
+ const loop = (t: number) => {
+ this._r = raf(loop);
+ if (!startTime) startTime = t;
+ if (t - lastTime > interval) {
+ lastTime = t;
+ this.setState({
+ time: t - startTime,
+ tick: this.state.tick + 1,
+ });
+ }
+ };
+ this._r = raf(loop);
+ }
+ componentWillUnmount() {
+ raf.cancel(this._r);
+ }
+ render() {
+ return ;
+ }
+ };
+
+ hoistNonReactStatics(TL, C);
+
+ return TL;
+}
diff --git a/cookbook-rn/HelloGL.js b/cookbook-rn/src/HelloGL.js
similarity index 100%
rename from cookbook-rn/HelloGL.js
rename to cookbook-rn/src/HelloGL.js
diff --git a/cookbook-rn/HelloTexture.js b/cookbook-rn/src/HelloTexture.js
similarity index 100%
rename from cookbook-rn/HelloTexture.js
rename to cookbook-rn/src/HelloTexture.js
diff --git a/cookbook-rn/src/Home.js b/cookbook-rn/src/Home.js
new file mode 100644
index 0000000..af810b0
--- /dev/null
+++ b/cookbook-rn/src/Home.js
@@ -0,0 +1,99 @@
+
+import React from "react";
+import {
+ Image,
+ StyleSheet,
+ Text,
+ ScrollView,
+ View,
+} from "react-native";
+import ListItem from "./ListItem";
+import * as examples from "./examples";
+import Router from "./Router";
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: "#fff",
+ flexDirection: "column",
+ },
+ list: {
+ flex: 1,
+ },
+ subHeader: {
+ padding: 10,
+ backgroundColor: "#f9f9f9",
+ },
+ subHeaderText: {
+ color: "#333",
+ fontSize: 12,
+ fontStyle: "italic",
+ },
+ title: {
+ flex: 1,
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ titleImage: {
+ width: 24,
+ height: 24,
+ marginRight: 12,
+ },
+ titleText: {
+ fontWeight: "bold",
+ color: "#fff",
+ fontSize: 18,
+ },
+});
+
+export default class Home extends React.Component {
+ static route = {
+ navigationBar: {
+ renderTitle: () =>
+
+ gl-react-native
+
+ },
+ };
+ props: {
+ navigator: *,
+ };
+ render() {
+ const {navigator} = this.props;
+ return (
+
+
+
+ a React Native library to write and compose WebGL shaders
+
+
+
+
+
+ Here is a collection of gl-react-native examples:
+
+
+
+ {Object.keys(examples).map(ex => {
+ const { title, description, Example } = examples[ex];
+ return navigator.push(Router.getRoute(ex))
+ : null
+ }
+ />;
+ })}
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/IvpoR40.jpg b/cookbook-rn/src/IvpoR40.jpg
new file mode 100644
index 0000000..a2170c2
Binary files /dev/null and b/cookbook-rn/src/IvpoR40.jpg differ
diff --git a/cookbook-rn/src/ListItem.js b/cookbook-rn/src/ListItem.js
new file mode 100644
index 0000000..e8b7133
--- /dev/null
+++ b/cookbook-rn/src/ListItem.js
@@ -0,0 +1,47 @@
+//@flow
+import React from "react";
+import {
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+} from "react-native";
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: "#fff",
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ borderBottomColor: "rgba(0, 0, 0, .1)",
+ paddingVertical: 10,
+ paddingHorizontal: 14,
+ },
+ title: {
+ fontSize: 16,
+ fontWeight: "bold",
+ color: "#222",
+ margin: 2,
+ },
+ titleDisabled: {
+ color: "#aaa",
+ },
+ description: {
+ fontSize: 12,
+ color: "#888",
+ margin: 2,
+ },
+});
+
+type Props = {
+ title: string,
+ description: string,
+ onPress: Function,
+ disabled?: boolean,
+};
+
+export default function ListItem({ title, description, onPress, disabled }: Props) {
+ return (
+
+ {title}
+ {description}
+
+ );
+}
diff --git a/cookbook-rn/src/MnOB9Le.jpg b/cookbook-rn/src/MnOB9Le.jpg
new file mode 100644
index 0000000..19a846e
Binary files /dev/null and b/cookbook-rn/src/MnOB9Le.jpg differ
diff --git a/cookbook-rn/src/NjbLHx2.jpg b/cookbook-rn/src/NjbLHx2.jpg
new file mode 100644
index 0000000..b381cd7
Binary files /dev/null and b/cookbook-rn/src/NjbLHx2.jpg differ
diff --git a/cookbook-rn/src/Otbz312.jpg b/cookbook-rn/src/Otbz312.jpg
new file mode 100644
index 0000000..01f4c9b
Binary files /dev/null and b/cookbook-rn/src/Otbz312.jpg differ
diff --git a/cookbook-rn/src/Router.js b/cookbook-rn/src/Router.js
new file mode 100644
index 0000000..7c2fc3b
--- /dev/null
+++ b/cookbook-rn/src/Router.js
@@ -0,0 +1,16 @@
+//@flow
+import {
+ createRouter,
+} from "@exponent/ex-navigation";
+import * as examples from "./examples";
+import Home from "./Home";
+import makeExample from "./makeExample";
+export default createRouter(() => {
+ const routes = {
+ home: () => Home,
+ };
+ Object.keys(examples).map(k => {
+ routes[k] = () => makeExample(examples[k], k);
+ });
+ return routes;
+});
diff --git a/cookbook-rn/src/SzbbUvX.jpg b/cookbook-rn/src/SzbbUvX.jpg
new file mode 100644
index 0000000..f4f24dd
Binary files /dev/null and b/cookbook-rn/src/SzbbUvX.jpg differ
diff --git a/cookbook-rn/src/YqsZKgc.jpg b/cookbook-rn/src/YqsZKgc.jpg
new file mode 100644
index 0000000..0f19ae9
Binary files /dev/null and b/cookbook-rn/src/YqsZKgc.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/index.js b/cookbook-rn/src/examples/_TODO_blurimgtitle/index.js
new file mode 100644
index 0000000..74ad498
--- /dev/null
+++ b/cookbook-rn/src/examples/_TODO_blurimgtitle/index.js
@@ -0,0 +1,165 @@
+//@flow
+import React, { PureComponent, Component, PropTypes } from "react";
+import { Shaders, Node, GLSL, Bus, LinearCopy } from "gl-react";
+import { Surface } from "gl-react-native";
+import JSON2D from "react-json2d";
+import {Blur1D} from "../blurxy";
+import {Blur} from "../blurmulti";
+import {BlurV} from "../blurmap";
+
+const shaders = Shaders.create({
+ ImageTitle: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D img, imgBlurred, imgTone, title, blurMap;
+uniform float colorThreshold;
+float monochrome (vec3 c) {
+ return 0.2125 * c.r + 0.7154 * c.g + 0.0721 * c.b;
+}
+void main() {
+ float blurFactor = texture2D(blurMap, uv).r;
+ vec4 bgColor = mix(
+ texture2D(img, uv),
+ texture2D(imgBlurred, uv),
+ step(0.01, blurFactor)
+ );
+ vec4 textColor = vec4(vec3(
+ step(monochrome(texture2D(imgTone, uv).rgb), colorThreshold)
+ ), 1.0);
+ float isText = 1.0 - texture2D(title, uv).r;
+ gl_FragColor = mix(bgColor, textColor, isText);
+}`
+ },
+ TitleBlurMap: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+uniform float threshold;
+void main() {
+gl_FragColor = vec4(
+ vec3(smoothstep(1.0, threshold, texture2D(t, uv).r)),
+ 1.0);
+}`
+ },
+});
+
+const AveragePixels = ({ children, quality }) =>
+
+
+ {children}
+
+ ;
+
+const TitleBlurMap = ({ children: title, threshold }) =>
+
+ {title}
+
+ }}
+ width={64}
+ height={64}
+ />;
+
+class Title extends PureComponent {
+ render () {
+ const { children, width, height } = this.props;
+ return {{
+ size: [ width, height ],
+ background: "#fff",
+ draws: [
+ {
+ "font": "bold 78px Didot,Georgia,serif",
+ "fillStyle": "#000",
+ "textBaseline": "top",
+ "textAlign": "center"
+ },
+ [ "fillText", children, width/2, 10, 84 ],
+ ]
+ }};
+ }
+}
+
+class ImageTitle extends Component {
+ static contextTypes = {
+ width: PropTypes.number.isRequired,
+ height: PropTypes.number.isRequired,
+ };
+ render() {
+ const { children: img, text, colorThreshold } = this.props;
+ const { width, height } = this.context;
+ return (
+ this.refs.imgBlurred,
+ title:() => this.refs.title,
+ imgTone:() => this.refs.imgTone,
+ blurMap:() => this.refs.blurMap,
+ }}>
+
+
+
+ {text}
+
+
+
+
+
+ {() => this.refs.title}
+
+
+
+
+
+ {img}
+
+
+
+
+ this.refs.blurMap}
+ factor={4}
+ passes={4}>
+ {img}
+
+
+
+
+ );
+ }
+}
+
+export default class Example extends Component {
+ render() {
+ const { title, colorThreshold, image } = this.props;
+ return (
+
+
+ {image}
+
+
+ );
+ }
+
+ static defaultProps = {
+ title: "Hello\nSan Francisco\n☻",
+ colorThreshold: 0.6,
+ image: require("./sf-6.jpg"),
+ };
+}
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/meta.js b/cookbook-rn/src/examples/_TODO_blurimgtitle/meta.js
new file mode 100644
index 0000000..c48e0ed
--- /dev/null
+++ b/cookbook-rn/src/examples/_TODO_blurimgtitle/meta.js
@@ -0,0 +1,36 @@
+import ImagesPicker from "../../toolbox/ImagesPicker";
+import makeTextArea from "../../toolbox/makeTextArea";
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+
+export const title = "Dynamic Blur Image Title";
+
+export const toolbox = [
+ { prop: "title",
+ title: "Title",
+ Editor: makeTextArea({
+ height: 140,
+ padding: 6,
+ fontFamily: "Didot,Georgia,serif",
+ fontSize: "36px",
+ lineHeight: "42px",
+ fontWeight: "bold",
+ textAlign: "center",
+ }) },
+ { prop: "colorThreshold",
+ title: "Color Threshold",
+ Editor: makeFloatSlider(0, 1, 0.01) }, // FIXME black <-> white
+ { prop: "image",
+ title: "Image",
+ Editor: ImagesPicker,
+ style: { width: 400 },
+ imageStyle: { maxWidth: 56, maxHeight: 56, marginBottom: 16, },
+ images: [
+ require("./sf-1.jpg"),
+ require("./sf-2.jpg"),
+ require("./sf-3.jpg"),
+ require("./sf-4.jpg"),
+ require("./sf-5.jpg"),
+ require("./sf-6.jpg"),
+ require("./sf-7.jpg"),
+ ] },
+];
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-1.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-1.jpg
new file mode 100644
index 0000000..ecf1d69
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-1.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-2.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-2.jpg
new file mode 100644
index 0000000..bf98e68
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-2.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-3.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-3.jpg
new file mode 100644
index 0000000..a27d486
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-3.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-4.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-4.jpg
new file mode 100644
index 0000000..2f75b7d
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-4.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-5.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-5.jpg
new file mode 100644
index 0000000..c81c6de
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-5.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-6.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-6.jpg
new file mode 100644
index 0000000..b73a869
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-6.jpg differ
diff --git a/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-7.jpg b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-7.jpg
new file mode 100644
index 0000000..710bec7
Binary files /dev/null and b/cookbook-rn/src/examples/_TODO_blurimgtitle/sf-7.jpg differ
diff --git a/cookbook-rn/src/examples/animated/index.js b/cookbook-rn/src/examples/animated/index.js
new file mode 100644
index 0000000..4e2b9db
--- /dev/null
+++ b/cookbook-rn/src/examples/animated/index.js
@@ -0,0 +1,54 @@
+//@flow
+import React, { Component } from "react";
+import { Animated, PanResponder, View } from "react-native";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import respondToTouchPosition from "../../HOC/respondToTouchPosition";
+
+const shaders = Shaders.create({
+ cursor: { frag: GLSL`
+precision lowp float; varying vec2 uv; uniform vec2 style;
+void main() {
+ float dist = pow(1.0 - distance(style, uv), 8.0);
+ gl_FragColor = vec4(smoothstep(2.0, 0.2, distance(style, uv)) * vec3(
+ 1.0 * dist + pow(1.0 - distance(style.y, uv.y), 16.0),
+ 0.5 * dist + pow(1.0 - distance(style.y, uv.y), 32.0),
+ 0.2 * dist + pow(1.0 - distance(style.x, uv.x), 32.0)), 1.0);
+}` }
+});
+
+class Cursor extends Component {
+ render() {
+ const { style: { x, y } } = this.props;
+ return ;
+ }
+}
+
+// using "style" is a hack. see https://github.com/animatedjs/animated/issues/45
+const AnimatedCursor = Animated.createAnimatedComponent(Cursor);
+
+export default respondToTouchPosition(class Example extends Component {
+ props: {
+ touchPosition: {
+ x: number,
+ y: number,
+ },
+ };
+ state = {
+ style: new Animated.ValueXY(this.props.touchPosition)
+ };
+ componentWillReceiveProps ({ touchPosition }) {
+ if (this.props.touchPosition !== touchPosition) {
+ Animated.spring(this.state.style, {
+ toValue: touchPosition,
+ }).start();
+ }
+ }
+ render() {
+ return (
+
+
+
+ );
+ }
+});
diff --git a/cookbook-rn/src/examples/animated/meta.js b/cookbook-rn/src/examples/animated/meta.js
new file mode 100644
index 0000000..f354047
--- /dev/null
+++ b/cookbook-rn/src/examples/animated/meta.js
@@ -0,0 +1 @@
+export const title = "Cursor spring effect with animated";
diff --git a/cookbook-rn/src/examples/blurmap/index.js b/cookbook-rn/src/examples/blurmap/index.js
new file mode 100644
index 0000000..0aed353
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmap/index.js
@@ -0,0 +1,67 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL, connectSize } from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ blurV1D: {
+ frag: GLSL`precision highp float;
+varying vec2 uv;
+uniform sampler2D t, map;
+uniform vec2 direction, resolution;
+vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
+ vec4 color = vec4(0.0);
+ vec2 off1 = vec2(1.3846153846) * direction;
+ vec2 off2 = vec2(3.2307692308) * direction;
+ color += texture2D(image, uv) * 0.2270270270;
+ color += texture2D(image, uv + (off1 / resolution)) * 0.3162162162;
+ color += texture2D(image, uv - (off1 / resolution)) * 0.3162162162;
+ color += texture2D(image, uv + (off2 / resolution)) * 0.0702702703;
+ color += texture2D(image, uv - (off2 / resolution)) * 0.0702702703;
+ return color;
+}
+void main() {
+ gl_FragColor = blur9(t, uv, resolution, direction * texture2D(map, uv).rg);
+}` }
+});
+
+// Same concept than Blur1D except it takes one more prop:
+// a map texture that tells the blur intensity for a given position.
+export const BlurV1D =
+ connectSize(({ children: t, direction, map, width, height }) =>
+ );
+
+// And its N-pass version
+import {directionForPass} from "../blurmulti";
+export const BlurV =
+ connectSize(({ children, factor, map, passes }) => {
+ const rec = pass =>
+ pass <= 0
+ ? children
+ :
+ {rec(pass-1)}
+ ;
+ return rec(passes);
+ });
+
+export default class Example extends Component {
+ render() {
+ const { factor, passes, map } = this.props;
+ return (
+
+
+ {require("../../NjbLHx2.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ factor: 2,
+ passes: 4,
+ map: StaticBlurMap.images[0],
+ };
+}
+import StaticBlurMap from "../../toolbox/StaticBlurMap";
diff --git a/cookbook-rn/src/examples/blurmap/meta.js b/cookbook-rn/src/examples/blurmap/meta.js
new file mode 100644
index 0000000..9dab93f
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmap/meta.js
@@ -0,0 +1,14 @@
+import StaticBlurMap from "../../toolbox/StaticBlurMap";
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "Blur with intensity map & multi-pass";
+export const toolbox = [
+ { prop: "factor",
+ title: "Blur",
+ Editor: makeFloatSlider(0, 8, 0.2) },
+ { prop: "passes",
+ title: value => `Blur Passes (${value})`,
+ Editor: makeFloatSlider(1, 8, 1) },
+ { prop: "map",
+ title: "Blur Texture Map",
+ Editor: StaticBlurMap },
+];
diff --git a/cookbook-rn/src/examples/blurmapdyn/index.js b/cookbook-rn/src/examples/blurmapdyn/index.js
new file mode 100644
index 0000000..8adc89b
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmapdyn/index.js
@@ -0,0 +1,46 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, Bus, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import {BlurV} from "../blurmap";
+import timeLoop from "../../HOC/timeLoop";
+
+const shaders = Shaders.create({
+ ConicalGradiant: {
+ frag: GLSL`precision highp float;
+varying vec2 uv;
+uniform float phase;
+const float PI = 3.14159;
+void main () {
+ gl_FragColor = vec4(vec3(
+ mod(phase + atan(uv.x-0.5, uv.y-0.5)/(2.0*PI), 1.0)
+ ), 1.0);
+}` }
+});
+
+const ConicalGradiantLoop = timeLoop(({ time }) =>
+ );
+
+export default class Example extends Component {
+ render() {
+ const { factor, passes } = this.props;
+ // also needs to be computed once.
+ return (
+
+
+
+
+ this.refs.blurMapBus} passes={passes} factor={factor}>
+ {require("../../NjbLHx2.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ factor: 6,
+ passes: 4,
+ };
+}
diff --git a/cookbook-rn/src/examples/blurmapdyn/meta.js b/cookbook-rn/src/examples/blurmapdyn/meta.js
new file mode 100644
index 0000000..fa59c05
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmapdyn/meta.js
@@ -0,0 +1,11 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "Blur with dynamic shader mapping";
+export const desc = "Any arbitrary shader can be used as a blur map!";
+export const toolbox = [
+ { prop: "factor",
+ title: "Blur",
+ Editor: makeFloatSlider(0, 8, 0.2) },
+ { prop: "passes",
+ title: value => `Blur Passes (${value})`,
+ Editor: makeFloatSlider(1, 8, 1) },
+];
diff --git a/cookbook-rn/src/examples/blurmapmouse/index.js b/cookbook-rn/src/examples/blurmapmouse/index.js
new file mode 100644
index 0000000..5434025
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmapmouse/index.js
@@ -0,0 +1,61 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, Bus, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import {BlurV} from "../blurmap";
+import respondToTouchPosition from "../../HOC/respondToTouchPosition";
+
+const shaders = Shaders.create({
+ Offset: {
+ frag: GLSL`precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+uniform vec2 offset;
+void main () {
+ gl_FragColor = texture2D(t, uv + offset);
+}`
+ }
+});
+
+const Offset = ({ t, offset }) =>
+ ;
+
+const Example = respondToTouchPosition(class Example extends Component {
+ render() {
+ const { map, touching, touchPosition } = this.props;
+// Sharing computation of a GL Node.
+// should not be passed straight to BlurV's map because
+// it would duplicates it in the tree ([passes] times)
+// Instead, we need to express a graph and share the
+// computation with a Bus ref.
+// We pass to BlurV's map prop a function that resolve that ref.
+ return (
+
+
+
+
+ this.refs.blurMapBus} passes={6} factor={6}>
+ {require("../../NjbLHx2.jpg")}
+
+
+ );
+ }
+});
+
+Example.defaultProps = {
+ map: StaticBlurMap.images[0],
+};
+
+export default Example;
+
+import StaticBlurMap from "../../toolbox/StaticBlurMap";
diff --git a/cookbook-rn/src/examples/blurmapmouse/meta.js b/cookbook-rn/src/examples/blurmapmouse/meta.js
new file mode 100644
index 0000000..a1541c9
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmapmouse/meta.js
@@ -0,0 +1,8 @@
+import StaticBlurMap from "../../toolbox/StaticBlurMap";
+export const title = "Blur map and Mouse position";
+export const description = "Dynamically change Blur Map with touch move";
+export const toolbox = [
+ { prop: "map",
+ title: "Blur Texture Map",
+ Editor: StaticBlurMap },
+];
diff --git a/cookbook-rn/src/examples/blurmulti/index.js b/cookbook-rn/src/examples/blurmulti/index.js
new file mode 100644
index 0000000..9b1ecce
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmulti/index.js
@@ -0,0 +1,45 @@
+//@flow
+import React, { Component } from "react";
+import { connectSize } from "gl-react";
+import { Surface } from "gl-react-native";
+import { Blur1D } from "../blurxy";
+
+// empirical strategy to chose a 2d vector for a blur pass
+const NORM = Math.sqrt(2)/2;
+export const directionForPass = (p: number, factor: number, total: number) => {
+ const f = factor * 2 * Math.ceil(p / 2) / total;
+ switch ((p-1) % 4) { // alternate horizontal, vertical and 2 diagonals
+ case 0: return [f,0];
+ case 1: return [0,f];
+ case 2: return [f*NORM,f*NORM];
+ default: return [f*NORM,-f*NORM];
+ }
+}
+
+// recursively apply Blur1D to make a multi pass Blur component
+export const Blur = connectSize(({ children, factor, passes }) => {
+ const rec = pass =>
+ pass <= 0
+ ? children
+ :
+ {rec(pass-1)}
+ ;
+ return rec(passes);
+});
+
+export default class Example extends Component {
+ render() {
+ const { factor, passes } = this.props;
+ return (
+
+
+ {require("../../iPKTONG.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ factor: 2,
+ passes: 4,
+ };
+}
diff --git a/cookbook-rn/src/examples/blurmulti/meta.js b/cookbook-rn/src/examples/blurmulti/meta.js
new file mode 100644
index 0000000..a29154d
--- /dev/null
+++ b/cookbook-rn/src/examples/blurmulti/meta.js
@@ -0,0 +1,11 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "multi-pass Blur";
+
+export const toolbox = [
+ { prop: "factor",
+ title: "Blur",
+ Editor: makeFloatSlider(0, 8, 0.2) },
+ { prop: "passes",
+ title: passes => `Blur Passes (${passes})`,
+ Editor: makeFloatSlider(0, 8, 1) },
+];
diff --git a/cookbook-rn/src/examples/blurxy/index.js b/cookbook-rn/src/examples/blurxy/index.js
new file mode 100644
index 0000000..2fae448
--- /dev/null
+++ b/cookbook-rn/src/examples/blurxy/index.js
@@ -0,0 +1,61 @@
+//@flow
+import React, { Component } from "react";
+import {Shaders, Node, GLSL, connectSize} from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ blur1D: { // blur9: from https://github.com/Jam3/glsl-fast-gaussian-blur
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+uniform vec2 direction, resolution;
+vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
+ vec4 color = vec4(0.0);
+ vec2 off1 = vec2(1.3846153846) * direction;
+ vec2 off2 = vec2(3.2307692308) * direction;
+ color += texture2D(image, uv) * 0.2270270270;
+ color += texture2D(image, uv + (off1 / resolution)) * 0.3162162162;
+ color += texture2D(image, uv - (off1 / resolution)) * 0.3162162162;
+ color += texture2D(image, uv + (off2 / resolution)) * 0.0702702703;
+ color += texture2D(image, uv - (off2 / resolution)) * 0.0702702703;
+ return color;
+}
+void main() {
+ gl_FragColor = blur9(t, uv, resolution, direction);
+}` }
+});
+
+// This implements a blur on a single direction (x or y axis for instance)
+// connectSize will inject for us the width/height from context if not provided
+export const Blur1D =
+ connectSize(({ children: t, direction, width, height }) =>
+ );
+
+// BlurXY is a basic blur that apply Blur1D on Y and then on X
+export const BlurXY =
+ connectSize(({ factor, children }) =>
+
+
+ {children}
+
+ );
+
+export default class Example extends Component {
+ render() {
+ const { factor } = this.props;
+ return (
+
+
+ {require("../../iPKTONG.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ factor: 1,
+ };
+}
diff --git a/cookbook-rn/src/examples/blurxy/meta.js b/cookbook-rn/src/examples/blurxy/meta.js
new file mode 100644
index 0000000..48fcec6
--- /dev/null
+++ b/cookbook-rn/src/examples/blurxy/meta.js
@@ -0,0 +1,8 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "simple Blur (2-passes)";
+
+export const toolbox = [
+ { prop: "factor",
+ title: "Blur",
+ Editor: makeFloatSlider(0, 8, 0.2) },
+];
diff --git a/cookbook-rn/src/examples/blurxydownscale/index.js b/cookbook-rn/src/examples/blurxydownscale/index.js
new file mode 100644
index 0000000..bdc9b7a
--- /dev/null
+++ b/cookbook-rn/src/examples/blurxydownscale/index.js
@@ -0,0 +1,24 @@
+//@flow
+import React, { Component } from "react";
+import {LinearCopy} from "gl-react";
+import { Surface } from "gl-react-native";
+import {BlurXY} from "../blurxy";
+
+export default class Example extends Component {
+ render() {
+ const { factor } = this.props;
+ return (
+
+
+
+ {require("../../iPKTONG.jpg")}
+
+
+
+// we have to wrap this in a so it upscales to the Surface size.
+ );
+ }
+ static defaultProps = {
+ factor: 0.5,
+ };
+}
diff --git a/cookbook-rn/src/examples/blurxydownscale/meta.js b/cookbook-rn/src/examples/blurxydownscale/meta.js
new file mode 100644
index 0000000..26c4302
--- /dev/null
+++ b/cookbook-rn/src/examples/blurxydownscale/meta.js
@@ -0,0 +1,8 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "simple Blur + downscale";
+
+export const toolbox = [
+ { prop: "factor",
+ title: "Blur",
+ Editor: makeFloatSlider(0.2, 0.8, 0.02) },
+];
diff --git a/cookbook-rn/src/examples/colordisc/index.js b/cookbook-rn/src/examples/colordisc/index.js
new file mode 100644
index 0000000..691c316
--- /dev/null
+++ b/cookbook-rn/src/examples/colordisc/index.js
@@ -0,0 +1,47 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+const shaders = Shaders.create({
+ ColoredDisc: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform vec3 fromColor, toColor;
+void main() {
+ float d = 2.0 * distance(uv, vec2(0.5));
+ gl_FragColor = mix(
+ vec4(mix(fromColor, toColor, d), 1.0),
+ vec4(0.0),
+ step(1.0, d)
+ );
+}` }
+});
+
+class ColoredDisc extends Component {
+ render() {
+ // fromColor/toColor must be array of 3 numbers because defined as vec3 type.
+ const { fromColor, toColor } = this.props;
+ return (
+
+ );
+ }
+}
+
+export default class Example extends Component {
+ render() {
+ const { fromColor, toColor } = this.props;
+ return (
+
+
+
+ );
+ }
+ static defaultProps = {
+ fromColor: [ 1, 0, 1 ],
+ toColor: [ 1, 1, 0 ],
+ };
+}
diff --git a/cookbook-rn/src/examples/colordisc/meta.js b/cookbook-rn/src/examples/colordisc/meta.js
new file mode 100644
index 0000000..bf02d53
--- /dev/null
+++ b/cookbook-rn/src/examples/colordisc/meta.js
@@ -0,0 +1,9 @@
+import Vec3ColorPicker from "../../toolbox/Vec3ColorPicker";
+export const toolbox = [
+ { prop: "fromColor", title: "fromColor", Editor: Vec3ColorPicker },
+ { prop: "toColor", title: "toColor", Editor: Vec3ColorPicker },
+];
+
+export const title = "Colored Disc";
+
+export const description = "Implement a simple radial gradient with {fromColor, toColor} uniforms.";
diff --git a/cookbook-rn/src/examples/colorscale/colorScales.js b/cookbook-rn/src/examples/colorscale/colorScales.js
new file mode 100644
index 0000000..07119de
--- /dev/null
+++ b/cookbook-rn/src/examples/colorscale/colorScales.js
@@ -0,0 +1,58 @@
+const ndarray = require("ndarray");
+
+module.exports = {
+ heatmap: ndarray(new Float64Array([
+ 1, 0, 0,
+ 1, 0.6, 0,
+ 0.4, 1, 0.4,
+ 0.1, 0.7, 1,
+ 0, 0, 1,
+ ]), [5, 1, 3]).step(-1, 1, 1),
+
+ monochrome: ndarray(new Float64Array([
+ 1, 1, 1,
+ 0.1, 0.2, 0.3,
+ ]), [2, 1, 3]).step(-1, 1, 1),
+
+ opacity: ndarray(new Float64Array([
+ 0,
+ 1,
+ ]), [2, 1, 1]).step(-1, 1, 1), // see gl-texture2d rule: https://github.com/stackgl/gl-texture2d#var-tex--createtexturegl-array
+
+ // from https://github.com/gka/chroma.js/blob/master/src/colors/colorbrewer.coffee
+ OrRd: ndarray(new Float64Array([1.00,0.97,0.93,1.00,0.91,0.78,0.99,0.83,0.62,0.99,0.73,0.52,0.99,0.55,0.35,0.94,0.40,0.28,0.84,0.19,0.12,0.70,0.00,0.00,0.50,0.00,0.00]), [9,1,3]).step(-1, 1, 1),
+ PuBu: ndarray(new Float64Array([1.00,0.97,0.98,0.93,0.91,0.95,0.82,0.82,0.90,0.65,0.74,0.86,0.45,0.66,0.81,0.21,0.56,0.75,0.02,0.44,0.69,0.02,0.35,0.55,0.01,0.22,0.35]), [9,1,3]).step(-1, 1, 1),
+ BuPu: ndarray(new Float64Array([0.97,0.99,0.99,0.88,0.93,0.96,0.75,0.83,0.90,0.62,0.74,0.85,0.55,0.59,0.78,0.55,0.42,0.69,0.53,0.25,0.62,0.51,0.06,0.49,0.30,0.00,0.29]), [9,1,3]).step(-1, 1, 1),
+ Oranges: ndarray(new Float64Array([1.00,0.96,0.92,1.00,0.90,0.81,0.99,0.82,0.64,0.99,0.68,0.42,0.99,0.55,0.24,0.95,0.41,0.07,0.85,0.28,0.00,0.65,0.21,0.01,0.50,0.15,0.02]), [9,1,3]).step(-1, 1, 1),
+ BuGn: ndarray(new Float64Array([0.97,0.99,0.99,0.90,0.96,0.98,0.80,0.93,0.90,0.60,0.85,0.79,0.40,0.76,0.64,0.25,0.68,0.46,0.14,0.55,0.27,0.00,0.43,0.17,0.00,0.27,0.11]), [9,1,3]).step(-1, 1, 1),
+ YlOrBr: ndarray(new Float64Array([1.00,1.00,0.90,1.00,0.97,0.74,1.00,0.89,0.57,1.00,0.77,0.31,1.00,0.60,0.16,0.93,0.44,0.08,0.80,0.30,0.01,0.60,0.20,0.02,0.40,0.15,0.02]), [9,1,3]).step(-1, 1, 1),
+ YlGn: ndarray(new Float64Array([1.00,1.00,0.90,0.97,0.99,0.73,0.85,0.94,0.64,0.68,0.87,0.56,0.47,0.78,0.47,0.25,0.67,0.36,0.14,0.52,0.26,0.00,0.41,0.22,0.00,0.27,0.16]), [9,1,3]).step(-1, 1, 1),
+ Reds: ndarray(new Float64Array([1.00,0.96,0.94,1.00,0.88,0.82,0.99,0.73,0.63,0.99,0.57,0.45,0.98,0.42,0.29,0.94,0.23,0.17,0.80,0.09,0.11,0.65,0.06,0.08,0.40,0.00,0.05]), [9,1,3]).step(-1, 1, 1),
+ RdPu: ndarray(new Float64Array([1.00,0.97,0.95,0.99,0.88,0.87,0.99,0.77,0.75,0.98,0.62,0.71,0.97,0.41,0.63,0.87,0.20,0.59,0.68,0.00,0.49,0.48,0.00,0.47,0.29,0.00,0.42]), [9,1,3]).step(-1, 1, 1),
+ Greens: ndarray(new Float64Array([0.97,0.99,0.96,0.90,0.96,0.88,0.78,0.91,0.75,0.63,0.85,0.61,0.45,0.77,0.46,0.25,0.67,0.36,0.14,0.55,0.27,0.00,0.43,0.17,0.00,0.27,0.11]), [9,1,3]).step(-1, 1, 1),
+ YlGnBu: ndarray(new Float64Array([1.00,1.00,0.85,0.93,0.97,0.69,0.78,0.91,0.71,0.50,0.80,0.73,0.25,0.71,0.77,0.11,0.57,0.75,0.13,0.37,0.66,0.15,0.20,0.58,0.03,0.11,0.35]), [9,1,3]).step(-1, 1, 1),
+ Purples: ndarray(new Float64Array([0.99,0.98,0.99,0.94,0.93,0.96,0.85,0.85,0.92,0.74,0.74,0.86,0.62,0.60,0.78,0.50,0.49,0.73,0.42,0.32,0.64,0.33,0.15,0.56,0.25,0.00,0.49]), [9,1,3]).step(-1, 1, 1),
+ GnBu: ndarray(new Float64Array([0.97,0.99,0.94,0.88,0.95,0.86,0.80,0.92,0.77,0.66,0.87,0.71,0.48,0.80,0.77,0.31,0.70,0.83,0.17,0.55,0.75,0.03,0.41,0.67,0.03,0.25,0.51]), [9,1,3]).step(-1, 1, 1),
+ Greys: ndarray(new Float64Array([1.00,1.00,1.00,0.94,0.94,0.94,0.85,0.85,0.85,0.74,0.74,0.74,0.59,0.59,0.59,0.45,0.45,0.45,0.32,0.32,0.32,0.15,0.15,0.15,0.00,0.00,0.00]), [9,1,3]).step(-1, 1, 1),
+ YlOrRd: ndarray(new Float64Array([1.00,1.00,0.80,1.00,0.93,0.63,1.00,0.85,0.46,1.00,0.70,0.30,0.99,0.55,0.24,0.99,0.31,0.16,0.89,0.10,0.11,0.74,0.00,0.15,0.50,0.00,0.15]), [9,1,3]).step(-1, 1, 1),
+ PuRd: ndarray(new Float64Array([0.97,0.96,0.98,0.91,0.88,0.94,0.83,0.73,0.85,0.79,0.58,0.78,0.87,0.40,0.69,0.91,0.16,0.54,0.81,0.07,0.34,0.60,0.00,0.26,0.40,0.00,0.12]), [9,1,3]).step(-1, 1, 1),
+ Blues: ndarray(new Float64Array([0.97,0.98,1.00,0.87,0.92,0.97,0.78,0.86,0.94,0.62,0.79,0.88,0.42,0.68,0.84,0.26,0.57,0.78,0.13,0.44,0.71,0.03,0.32,0.61,0.03,0.19,0.42]), [9,1,3]).step(-1, 1, 1),
+ PuBuGn: ndarray(new Float64Array([1.00,0.97,0.98,0.93,0.89,0.94,0.82,0.82,0.90,0.65,0.74,0.86,0.40,0.66,0.81,0.21,0.56,0.75,0.01,0.51,0.54,0.00,0.42,0.35,0.00,0.27,0.21]), [9,1,3]).step(-1, 1, 1),
+ Spectral: ndarray(new Float64Array([0.62,0.00,0.26,0.84,0.24,0.31,0.96,0.43,0.26,0.99,0.68,0.38,1.00,0.88,0.55,1.00,1.00,0.75,0.90,0.96,0.60,0.67,0.87,0.64,0.40,0.76,0.65,0.20,0.53,0.74,0.37,0.31,0.64]), [11,1,3]).step(-1, 1, 1),
+ RdYlGn: ndarray(new Float64Array([0.65,0.00,0.15,0.84,0.19,0.15,0.96,0.43,0.26,0.99,0.68,0.38,1.00,0.88,0.55,1.00,1.00,0.75,0.85,0.94,0.55,0.65,0.85,0.42,0.40,0.74,0.39,0.10,0.60,0.31,0.00,0.41,0.22]), [11,1,3]).step(-1, 1, 1),
+ RdBu: ndarray(new Float64Array([0.40,0.00,0.12,0.70,0.09,0.17,0.84,0.38,0.30,0.96,0.65,0.51,0.99,0.86,0.78,0.97,0.97,0.97,0.82,0.90,0.94,0.57,0.77,0.87,0.26,0.58,0.76,0.13,0.40,0.67,0.02,0.19,0.38]), [11,1,3]).step(-1, 1, 1),
+ PiYG: ndarray(new Float64Array([0.56,0.00,0.32,0.77,0.11,0.49,0.87,0.47,0.68,0.95,0.71,0.85,0.99,0.88,0.94,0.97,0.97,0.97,0.90,0.96,0.82,0.72,0.88,0.53,0.50,0.74,0.25,0.30,0.57,0.13,0.15,0.39,0.10]), [11,1,3]).step(-1, 1, 1),
+ PRGn: ndarray(new Float64Array([0.25,0.00,0.29,0.46,0.16,0.51,0.60,0.44,0.67,0.76,0.65,0.81,0.91,0.83,0.91,0.97,0.97,0.97,0.85,0.94,0.83,0.65,0.86,0.63,0.35,0.68,0.38,0.11,0.47,0.22,0.00,0.27,0.11]), [11,1,3]).step(-1, 1, 1),
+ RdYlBu: ndarray(new Float64Array([0.65,0.00,0.15,0.84,0.19,0.15,0.96,0.43,0.26,0.99,0.68,0.38,1.00,0.88,0.56,1.00,1.00,0.75,0.88,0.95,0.97,0.67,0.85,0.91,0.45,0.68,0.82,0.27,0.46,0.71,0.19,0.21,0.58]), [11,1,3]).step(-1, 1, 1),
+ BrBG: ndarray(new Float64Array([0.33,0.19,0.02,0.55,0.32,0.04,0.75,0.51,0.18,0.87,0.76,0.49,0.96,0.91,0.76,0.96,0.96,0.96,0.78,0.92,0.90,0.50,0.80,0.76,0.21,0.59,0.56,0.00,0.40,0.37,0.00,0.24,0.19]), [11,1,3]).step(-1, 1, 1),
+ RdGy: ndarray(new Float64Array([0.40,0.00,0.12,0.70,0.09,0.17,0.84,0.38,0.30,0.96,0.65,0.51,0.99,0.86,0.78,1.00,1.00,1.00,0.88,0.88,0.88,0.73,0.73,0.73,0.53,0.53,0.53,0.30,0.30,0.30,0.10,0.10,0.10]), [11,1,3]).step(-1, 1, 1),
+ PuOr: ndarray(new Float64Array([0.50,0.23,0.03,0.70,0.35,0.02,0.88,0.51,0.08,0.99,0.72,0.39,1.00,0.88,0.71,0.97,0.97,0.97,0.85,0.85,0.92,0.70,0.67,0.82,0.50,0.45,0.67,0.33,0.15,0.53,0.18,0.00,0.29]), [11,1,3]).step(-1, 1, 1),
+ Set2: ndarray(new Float64Array([0.40,0.76,0.65,0.99,0.55,0.38,0.55,0.63,0.80,0.91,0.54,0.76,0.65,0.85,0.33,1.00,0.85,0.18,0.90,0.77,0.58,0.70,0.70,0.70]), [8,1,3]).step(-1, 1, 1),
+ Accent: ndarray(new Float64Array([0.50,0.79,0.50,0.75,0.68,0.83,0.99,0.75,0.53,1.00,1.00,0.60,0.22,0.42,0.69,0.94,0.01,0.50,0.75,0.36,0.09,0.40,0.40,0.40]), [8,1,3]).step(-1, 1, 1),
+ Set1: ndarray(new Float64Array([0.89,0.10,0.11,0.22,0.49,0.72,0.30,0.69,0.29,0.60,0.31,0.64,1.00,0.50,0.00,1.00,1.00,0.20,0.65,0.34,0.16,0.97,0.51,0.75,0.60,0.60,0.60]), [9,1,3]).step(-1, 1, 1),
+ Set3: ndarray(new Float64Array([0.55,0.83,0.78,1.00,1.00,0.70,0.75,0.73,0.85,0.98,0.50,0.45,0.50,0.69,0.83,0.99,0.71,0.38,0.70,0.87,0.41,0.99,0.80,0.90,0.85,0.85,0.85,0.74,0.50,0.74,0.80,0.92,0.77,1.00,0.93,0.44]), [12,1,3]).step(-1, 1, 1),
+ Dark2: ndarray(new Float64Array([0.11,0.62,0.47,0.85,0.37,0.01,0.46,0.44,0.70,0.91,0.16,0.54,0.40,0.65,0.12,0.90,0.67,0.01,0.65,0.46,0.11,0.40,0.40,0.40]), [8,1,3]).step(-1, 1, 1),
+ Paired: ndarray(new Float64Array([0.65,0.81,0.89,0.12,0.47,0.71,0.70,0.87,0.54,0.20,0.63,0.17,0.98,0.60,0.60,0.89,0.10,0.11,0.99,0.75,0.44,1.00,0.50,0.00,0.79,0.70,0.84,0.42,0.24,0.60,1.00,1.00,0.60,0.69,0.35,0.16]), [12,1,3]).step(-1, 1, 1),
+ Pastel2: ndarray(new Float64Array([0.70,0.89,0.80,0.99,0.80,0.67,0.80,0.84,0.91,0.96,0.79,0.89,0.90,0.96,0.79,1.00,0.95,0.68,0.95,0.89,0.80,0.80,0.80,0.80]), [8,1,3]).step(-1, 1, 1),
+ Pastel1: ndarray(new Float64Array([0.98,0.71,0.68,0.70,0.80,0.89,0.80,0.92,0.77,0.87,0.80,0.89,1.00,0.85,0.65,1.00,1.00,0.80,0.90,0.85,0.74,0.99,0.85,0.93,0.95,0.95,0.95]), [9,1,3]).step(-1, 1, 1),
+};
diff --git a/cookbook-rn/src/examples/colorscale/index.js b/cookbook-rn/src/examples/colorscale/index.js
new file mode 100644
index 0000000..674aa45
--- /dev/null
+++ b/cookbook-rn/src/examples/colorscale/index.js
@@ -0,0 +1,44 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import colorScales from "./colorScales"; export {colorScales};
+
+const shaders = Shaders.create({
+ colorify: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D children, colorScale;
+float greyscale (vec3 c) { return 0.2125 * c.r + 0.7154 * c.g + 0.0721 * c.b; }
+void main() {
+ vec4 original = texture2D(children, uv);
+ vec4 newcolor = texture2D(colorScale, vec2(greyscale(original.rgb), 0.5));
+ gl_FragColor = vec4(newcolor.rgb, original.a * newcolor.a);
+}` }
+});
+
+export const Colorify =
+({ children, colorScale, interpolation }) =>
+ ;
+
+export default class Example extends Component {
+ render() {
+ const { interpolation, color } = this.props;
+ return (
+
+
+ {require("../../iPKTONG.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ interpolation: "linear",
+ color: Object.keys(colorScales)[0],
+ };
+}
diff --git a/cookbook-rn/src/examples/colorscale/meta.js b/cookbook-rn/src/examples/colorscale/meta.js
new file mode 100644
index 0000000..9709312
--- /dev/null
+++ b/cookbook-rn/src/examples/colorscale/meta.js
@@ -0,0 +1,27 @@
+import React from "react";
+import colorScales from "./colorScales";
+import makeSelect from "../../toolbox/makeSelect";
+import { LinearCopy, NearestCopy } from "gl-react";
+import { Surface } from "gl-react-native";
+
+export const title = "color mapping with gradient texture";
+export const description = "A gradient texture defines the color mapping of the image greyscale.";
+
+export const toolbox = [
+ { prop: "color",
+ title: "color scale",
+ Editor: makeSelect(Object.keys(colorScales).map(cs =>
+ ({ key: cs, label: cs }))) },
+ { prop: "interpolation",
+ Editor: makeSelect([
+ { key: "linear", label: "linear interpolation" },
+ { key: "nearest", label: "nearest interpolation" },
+ ]) }
+];
+
+export const ToolboxFooter = ({ color, interpolation }) =>
+
+ { interpolation==="linear"
+ ? {colorScales[color]}
+ : {colorScales[color]} }
+ ;
diff --git a/cookbook-rn/src/examples/demodesert/index.js b/cookbook-rn/src/examples/demodesert/index.js
new file mode 100644
index 0000000..6e92926
--- /dev/null
+++ b/cookbook-rn/src/examples/demodesert/index.js
@@ -0,0 +1,226 @@
+//@flow
+import React from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+import shadertoyTex17jpg from "./shadertoy-tex17.jpg";
+
+const shaders = Shaders.create({
+ desertPassage: {
+// from https://www.shadertoy.com/view/XtyGzc
+ frag: GLSL`
+precision mediump float;
+varying vec2 uv;
+uniform float iGlobalTime;
+uniform sampler2D iChannel0;
+#define FAR 80.
+mat2 rot2( float th ){ vec2 a = sin(vec2(1.5707963, 0) + th); return mat2(a, -a.y, a.x); }
+float hash( float n ){ return fract(cos(n)*45758.5453); }
+float hash( vec3 p ){ return fract(sin(dot(p, vec3(7, 157, 113)))*45758.5453); }
+float drawObject(in vec3 p){ p = fract(p)-.5; return dot(p, p); }
+float cellTile(in vec3 p){
+ vec4 d;
+ d.x = drawObject(p - vec3(.81, .62, .53));
+ p.xy = vec2(p.y-p.x, p.y + p.x)*.7071;
+ d.y = drawObject(p - vec3(.39, .2, .11));
+ p.yz = vec2(p.z-p.y, p.z + p.y)*.7071;
+ d.z = drawObject(p - vec3(.62, .24, .06));
+ p.xz = vec2(p.z-p.x, p.z + p.x)*.7071;
+ d.w = drawObject(p - vec3(.2, .82, .64));
+ d.xy = min(d.xz, d.yw);
+ return min(d.x, d.y)*2.66;
+}
+vec2 path(in float z){ return vec2(20.*sin(z * .04), 4.*cos(z * .09) + 3.*(sin(z*.025) - 1.)); }
+float surfFunc(in vec3 p){
+ float c = cellTile(p/6.);
+ return mix(c, cos(c*6.283*2.)*.5 + .5, .125);
+}
+float smin(float a, float b , float s){
+ float h = clamp( 0.5 + 0.5*(b-a)/s, 0. , 1.);
+ return mix(b, a, h) - h*(1.0-h)*s;
+}
+float smax(float a, float b, float s){
+ float h = clamp( 0.5 + 0.5*(a-b)/s, 0., 1.);
+ return mix(b, a, h) + h*(1.0-h)*s;
+}
+float map(vec3 p){
+ float sf = surfFunc(p);
+ float cav = dot(cos(p*3.14159265/8.), sin(p.yzx*3.14159265/8.)) + 2.;
+ p.xy -= path(p.z);
+ float tun = 1.5 - length(p.xy*vec2(1, .4));
+ tun = smax(tun, 1.-cav, 2.) + .75 + (.5-sf);
+ float gr = p.y + 7. - cav*.5 + (.5-sf)*.5;
+ float rf = p.y - 15.;
+ return smax(smin(tun, gr, .1), rf, 1.);
+}
+float trace(in vec3 ro, in vec3 rd){
+ float t = 0., h;
+ for(int i=0; i<128; i++){
+ h = map(ro+rd*t);
+ if(abs(h)<0.002*(t*.25 + 1.) || t>FAR) break;
+ t += h*.8;
+ }
+ return min(t, FAR);
+}
+vec3 normal(in vec3 p)
+{
+ vec2 e = vec2(-1., 1.)*0.001;
+ return normalize(e.yxx*map(p + e.yxx) + e.xxy*map(p + e.xxy) +
+ e.xyx*map(p + e.xyx) + e.yyy*map(p + e.yyy) );
+}
+vec3 tex3D( sampler2D t, in vec3 p, in vec3 n ){
+ n = max(abs(n) - .2, .001);
+ n /= (n.x + n.y + n.z );
+ p = (texture2D(t, p.yz)*n.x + texture2D(t, p.zx)*n.y + texture2D(t, p.xy)*n.z).xyz;
+ return p*p;
+}
+vec3 doBumpMap( sampler2D tx, in vec3 p, in vec3 n, float bf){
+ const vec2 e = vec2(0.001, 0);
+ mat3 m = mat3( tex3D(tx, p - e.xyy, n), tex3D(tx, p - e.yxy, n), tex3D(tx, p - e.yyx, n));
+ vec3 g = vec3(0.299, 0.587, 0.114)*m;
+ g = (g - dot(tex3D(tx, p , n), vec3(0.299, 0.587, 0.114)) )/e.x; g -= n*dot(n, g);
+ return normalize( n + g*bf );
+}
+float n3D(in vec3 p){
+ const vec3 s = vec3(7, 157, 113);
+ vec3 ip = floor(p); p -= ip;
+ vec4 h = vec4(0., s.yz, s.y + s.z) + dot(ip, s);
+ p = p*p*(3. - 2.*p);
+ h = mix(fract(sin(h)*43758.5453), fract(sin(h + s.x)*43758.5453), p.x);
+ h.xy = mix(h.xz, h.yw, p.y);
+ return mix(h.x, h.y, p.z);
+}
+float bumpSurf3D( in vec3 p){
+ float bmp = cellTile(p/3.)*.8 + cellTile(p)*.2;
+ float ns = n3D(p*6. - bmp*6.);
+ return mix(bmp, 1. - abs(ns-.333)/.667, .05);
+}
+vec3 doBumpMap(in vec3 p, in vec3 nor, float bumpfactor){
+ const vec2 e = vec2(0.001, 0);
+ float ref = bumpSurf3D(p);
+ vec3 grad = (vec3(bumpSurf3D(p - e.xyy),
+ bumpSurf3D(p - e.yxy),
+ bumpSurf3D(p - e.yyx) )-ref)/e.x;
+ grad -= nor*dot(nor, grad);
+ return normalize( nor + grad*bumpfactor );
+}
+float softShadow(in vec3 ro, in vec3 rd, in float start, in float end, in float k){
+ float shade = 1.0;
+ const int maxIterationsShad = 10;
+ float dist = start;
+ float stepDist = end/float(maxIterationsShad);
+ for (int i=0; i end) break;
+ }
+ return min(max(shade, 0.) + .1, 1.);
+}
+float calculateAO( in vec3 p, in vec3 n)
+{
+ float ao = 0.0, l;
+ const float nbIte = 6.0;
+ const float maxDist = 3.;
+ for(float i=1.; i< nbIte+.5; i++ ){
+ l = (i*.66 + hash(i)*.34)/nbIte*maxDist;
+ ao += (l - map( p + n*l ))/(1.+ l);
+ }
+ return clamp( 1.-ao/nbIte, 0., 1.);
+}
+vec3 getSky(){ return vec3(2., 1.4, .7); }
+float trig3(in vec3 p){
+ p = cos(p*2. + (cos(p.yzx) + 1.)*1.57);
+ return dot(p, vec3(0.1666)) + 0.5;
+}
+float trigNoise3D(in vec3 p){
+ const mat3 m3RotTheta = mat3(0.25, -0.866, 0.433, 0.9665, 0.25, -0.2455127, -0.058, 0.433, 0.899519 )*1.5;
+ float res = 0.;
+ float t = trig3(p*3.14159265);
+ p += (t);
+ p = m3RotTheta*p;
+ res += t;
+ t = trig3(p*3.14159265);
+ p += (t)*0.7071;
+ p = m3RotTheta*p;
+ res += t*0.7071;
+ t = trig3(p*3.14159265);
+ res += t*0.5;
+ return res/2.2071;
+}
+float hash31(vec3 p){ return fract(sin(dot(p, vec3(127.1, 311.7, 74.7)))*43758.5453); }
+float getMist(in vec3 ro, in vec3 rd, in vec3 lp, in float t){
+ float mist = 0.;
+ ro += rd*t/3.;
+ for (int i = 0; i<3; i++){
+ float sDi = length(lp-ro)/FAR;
+ float sAtt = 1./(1. + sDi*0.1 + sDi*sDi*0.01);
+ mist += trigNoise3D(ro/2.)*sAtt;
+ ro += rd*t/3.;
+ }
+ return clamp(mist/1.5 + hash31(ro)*0.1-0.05, 0., 1.);
+}
+void main() {
+ vec2 u = uv * 2.0 - 1.0;
+ vec3 ro = vec3(0, 0, iGlobalTime*8.);
+ vec3 lookAt = ro + vec3(0, 0, .5);
+ ro.xy += path(ro.z);
+ lookAt.xy += path(lookAt.z);
+ float FOV = 3.14159265/2.5;
+ vec3 forward = normalize(lookAt - ro);
+ vec3 right = normalize(vec3(forward.z, 0, -forward.x ));
+ vec3 up = cross(forward, right);
+ vec3 rd = normalize(forward + FOV*u.x*right + FOV*u.y*up);
+ rd.xy = rot2( path(lookAt.z).x/64. )*rd.xy;
+ vec3 lp = vec3(FAR*.5, FAR, FAR) + vec3(0, 0, ro.z);
+ float t = trace(ro, rd);
+ vec3 sky = getSky();
+ vec3 col = sky;
+ vec3 sp = ro+t*rd;
+ float pathHeight = sp.y-path(sp.z).y;
+ if (t < FAR){
+ vec3 sn = normal( sp );
+ vec3 ld = lp-sp;
+ ld /= max(length(ld), 0.001);
+ const float tSize = 1./4.;
+ sn = doBumpMap(sp, sn, .75/(1. + t/FAR*.25));
+ float bf = (pathHeight + 5. < 0.)? .05: .025;
+ sn = doBumpMap(iChannel0, sp*tSize, sn, bf/(1. + t/FAR));
+ float shd = softShadow(sp, ld, 0.05, FAR, 8.);
+ float ao = calculateAO(sp, sn);
+ float dif = max( dot( ld, sn ), 0.0);
+ float spe = pow(max( dot( reflect(-ld, sn), -rd ), 0.0 ), 5.);
+ float fre = clamp(1.0 + dot(rd, sn), 0.0, 1.0);
+ float Schlick = pow( 1. - max(dot(rd, normalize(rd + ld)), 0.), 5.0);
+ float fre2 = mix(.2, 1., Schlick);
+ float amb = fre*fre2*.7 + .05;
+ col = clamp(mix(vec3(1.152, 0.4275,.153), vec3(.225, 0.05985, 0.0153), -sn.y*.5 + pathHeight*.5 + 1.75), vec3(.9, 0.534375, 0.239), vec3(.9, .855, .765));
+ col = smoothstep(-.5, 1., tex3D(iChannel0, sp*tSize, sn)*2.)*(col + vec3(.225, .21375, .19125));
+ col += smoothstep(0., 1., -pathHeight - 5.5)*fre*.25;
+ col += getSky()*fre*fre2;
+ col = (col*(dif + .1) + vec3(1)*fre2*spe)*shd*ao + amb*pow(col, vec3(2.));
+ }
+ float dust = getMist(ro, rd, lp, t)*(1.-clamp((pathHeight - 5.)*.125, 0., 1.));
+ sky = getSky()*mix(1., .75, dust);
+ col = mix(col, sky, min(t*t*1.5/FAR/FAR, 1.));
+ u = uv;
+ col = min(col, 1.)*pow( 16.0*u.x*u.y*(1.0-u.x)*(1.0-u.y) , .125);
+ gl_FragColor = vec4(sqrt(clamp(col, 0., 1.)), 1);
+}` }
+});
+
+const DesertPassage = ({ time }) =>
+
+
+export const DesertPassageLoop = timeLoop(DesertPassage, { frameRate: 30 });
+
+export default () =>
+
+
+
diff --git a/cookbook-rn/src/examples/demodesert/meta.js b/cookbook-rn/src/examples/demodesert/meta.js
new file mode 100644
index 0000000..03aaaf6
--- /dev/null
+++ b/cookbook-rn/src/examples/demodesert/meta.js
@@ -0,0 +1 @@
+export const title = "a Shadertoy more advanced example";
diff --git a/cookbook-rn/src/examples/demodesert/shadertoy-tex17.jpg b/cookbook-rn/src/examples/demodesert/shadertoy-tex17.jpg
new file mode 100644
index 0000000..cc0bfa7
Binary files /dev/null and b/cookbook-rn/src/examples/demodesert/shadertoy-tex17.jpg differ
diff --git a/cookbook-rn/src/examples/demodesertcrt/index.js b/cookbook-rn/src/examples/demodesertcrt/index.js
new file mode 100644
index 0000000..bdbd6d2
--- /dev/null
+++ b/cookbook-rn/src/examples/demodesertcrt/index.js
@@ -0,0 +1,160 @@
+//@flow
+import React, { Component, PureComponent } from "react";
+import { View, Button } from "react-native";
+import {Shaders, Node, GLSL, Bus, connectSize} from "gl-react";
+import { Surface } from "gl-react-native";
+import {DesertPassageLoop} from "../demodesert";
+
+const shaders = Shaders.create({
+ crt: {
+// adapted from http://bit.ly/2eR1iKi
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D rubyTexture;
+uniform vec2 rubyInputSize;
+uniform vec2 rubyOutputSize;
+uniform vec2 rubyTextureSize;
+uniform float distortion;
+#define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(inputGamma))
+#define FIX(c) max(abs(c), 1e-6);
+#define PI 3.141592653589
+#define phase 0.0
+#define inputGamma 2.2
+#define outputGamma 2.5
+vec2 radialDistortion(vec2 coord) {
+ coord *= rubyTextureSize / rubyInputSize;
+ vec2 cc = coord - 0.5;
+ float dist = dot(cc, cc) * distortion;
+ return (coord + cc * (1.0 + dist) * dist) * rubyInputSize / rubyTextureSize;
+}
+vec4 scanlineWeights(float distance, vec4 color)
+{
+ vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
+ vec4 weights = vec4(distance * 3.333333);
+ return 0.51 * exp(-pow(weights * sqrt(2.0 / wid), wid)) / (0.18 + 0.06 * wid);
+}
+void main()
+{
+ vec2 one = 1.0 / rubyTextureSize;
+ vec2 xy = radialDistortion(uv.xy);
+ vec2 uv_ratio = fract(xy * rubyTextureSize) - vec2(0.5);
+ xy = (floor(xy * rubyTextureSize) + vec2(0.5)) / rubyTextureSize;
+ vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
+ coeffs = FIX(coeffs);
+ coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
+ coeffs /= dot(coeffs, vec4(1.0));
+ vec4 col = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, 0.0)) + coeffs.y * TEX2D(xy) + coeffs.z * TEX2D(xy + vec2(one.x, 0.0)) + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, 0.0)), 0.0, 1.0);
+ vec4 col2 = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, one.y)) + coeffs.y * TEX2D(xy + vec2(0.0, one.y)) + coeffs.z * TEX2D(xy + one) + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, one.y)), 0.0, 1.0);
+ vec4 weights = scanlineWeights(abs(uv_ratio.y) , col);
+ vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
+ vec3 mul_res = (col * weights + col2 * weights2).xyz;
+ float mod_factor = uv.x * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x;
+ vec3 dotMaskWeights = mix(
+ vec3(1.05, 0.75, 1.05),
+ vec3(0.75, 1.05, 0.75),
+ floor(mod(mod_factor, 2.0))
+ );
+ mul_res *= dotMaskWeights;
+ mul_res = pow(mul_res, vec3(1.0 / (2.0 * inputGamma - outputGamma)));
+ gl_FragColor = vec4(mul_res, 1.0);
+}` },
+ copy: {
+ frag: GLSL`
+ precision highp float;
+ varying vec2 uv;
+ uniform sampler2D t;
+ void main(){
+ gl_FragColor=texture2D(t,uv);
+ }`,
+ }
+});
+
+class CRT extends Component {
+ props: {
+ children?: any,
+ distortion: number,
+ inSize: [number, number],
+ outSize: [number, number],
+ texSize: [number, number],
+ };
+ render() {
+ const { children, inSize, outSize, texSize, distortion } = this.props;
+ return ;
+ }
+}
+
+const Desert = connectSize(DesertPassageLoop);
+
+class ShowCaptured extends PureComponent {
+ render() {
+ const {t} = this.props;
+ return
+
+ ;
+ }
+}
+
+export default class Example extends Component {
+ state = {
+ surfacePixels: null,
+ desertPixels: null,
+ };
+
+ onCapture = () =>
+ this.setState({
+ surfacePixels: this.refs.surface.capture(),
+ desertPixels: this.refs.desert.capture(),
+ });
+
+ render() {
+ const { distortion } = this.props;
+ const { surfacePixels, desertPixels } = this.state;
+ return (
+
+
+
+ {/* we use a Bus to have a ref for capture */}
+
+
+
+
+ {() => this.refs.desert}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ static defaultProps = {
+ distortion: 0.2
+ };
+}
diff --git a/cookbook-rn/src/examples/demodesertcrt/meta.js b/cookbook-rn/src/examples/demodesertcrt/meta.js
new file mode 100644
index 0000000..e09796b
--- /dev/null
+++ b/cookbook-rn/src/examples/demodesertcrt/meta.js
@@ -0,0 +1,9 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+
+export const title = "Doom Shadertoy + CRT effect + snapshot()";
+
+export const toolbox = [
+ { prop: "distortion",
+ title: "Distortion",
+ Editor: makeFloatSlider(0, 1, 0.01) },
+];
diff --git a/cookbook-rn/src/examples/demotunnel/index.js b/cookbook-rn/src/examples/demotunnel/index.js
new file mode 100644
index 0000000..0bc49ae
--- /dev/null
+++ b/cookbook-rn/src/examples/demotunnel/index.js
@@ -0,0 +1,37 @@
+//@flow
+import React from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+
+const shaders = Shaders.create({
+ squareTunnel: {
+// from https://en.wikipedia.org/wiki/Shadertoy
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform float iGlobalTime;
+void main() {
+ vec2 p = 2.0 * uv - vec2(1.0);
+ float a = atan(p.y,p.x);
+ float r = pow( pow(p.x*p.x,4.0) + pow(p.y*p.y,4.0), 1.0/8.0 );
+ vec2 uv = vec2( 1.0/r + 0.2*iGlobalTime, a );
+ float f = cos(12.0*uv.x)*cos(6.0*uv.y);
+ vec3 col = 0.5 + 0.5*sin( 3.1416*f + vec3(0.0,0.5,1.0) );
+ col = col*r;
+ gl_FragColor = vec4( col, 1.0 );
+}` }
+});
+
+const SquareTunnel = ({ time }) =>
+
+
+const DesertPassageLoop = timeLoop(SquareTunnel);
+
+export default() =>
+
+
+
diff --git a/cookbook-rn/src/examples/demotunnel/meta.js b/cookbook-rn/src/examples/demotunnel/meta.js
new file mode 100644
index 0000000..25cb3c0
--- /dev/null
+++ b/cookbook-rn/src/examples/demotunnel/meta.js
@@ -0,0 +1 @@
+export const title = "a Shadertoy simple example";
diff --git a/cookbook-rn/src/examples/diamondanim/index.js b/cookbook-rn/src/examples/diamondanim/index.js
new file mode 100644
index 0000000..ca124c0
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondanim/index.js
@@ -0,0 +1,31 @@
+//@flow
+import React from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import { DiamondCrop } from "../diamondcrop";
+import timeLoop from "../../HOC/timeLoop";
+
+const shaders = Shaders.create({
+ helloRed: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform float red;
+void main() {
+ gl_FragColor = vec4(red, uv.x, uv.y, 1.0);
+}` }
+});
+
+const HelloGLAnimated = timeLoop( ({ time }) =>
+
+);
+
+export default () =>
+
+
+
+
+ ;
diff --git a/cookbook-rn/src/examples/diamondanim/meta.js b/cookbook-rn/src/examples/diamondanim/meta.js
new file mode 100644
index 0000000..f22c0c8
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondanim/meta.js
@@ -0,0 +1 @@
+export const title = "animated HelloGL (red) + DiamondCrop";
diff --git a/cookbook-rn/src/examples/diamondcrop/index.js b/cookbook-rn/src/examples/diamondcrop/index.js
new file mode 100644
index 0000000..b49b335
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondcrop/index.js
@@ -0,0 +1,34 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ DiamondCrop: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+void main() {
+gl_FragColor = mix(
+ texture2D(t, uv),
+ vec4(0.0),
+ step(0.5, abs(uv.x - 0.5) + abs(uv.y - 0.5))
+);
+}` },
+});
+
+export const DiamondCrop = ({ children: t }) =>
+ ;
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+ {require("../../5EOyTDQ.jpg")}
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/examples/diamondcrop/meta.js b/cookbook-rn/src/examples/diamondcrop/meta.js
new file mode 100644
index 0000000..200922d
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondcrop/meta.js
@@ -0,0 +1 @@
+export const title = "DiamondCrop on an image texture";
diff --git a/cookbook-rn/src/examples/diamondhello/index.js b/cookbook-rn/src/examples/diamondhello/index.js
new file mode 100644
index 0000000..ff3bc89
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondhello/index.js
@@ -0,0 +1,17 @@
+//@flow
+import React, { Component } from "react";
+import { Surface } from "gl-react-native";
+import { DiamondCrop } from "../diamondcrop";
+import { HelloBlue } from "../helloblue";
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/examples/diamondhello/meta.js b/cookbook-rn/src/examples/diamondhello/meta.js
new file mode 100644
index 0000000..ff87196
--- /dev/null
+++ b/cookbook-rn/src/examples/diamondhello/meta.js
@@ -0,0 +1 @@
+export const title = "HelloGL composed with DiamondCrop";
diff --git a/cookbook-rn/src/examples/distortion/index.js b/cookbook-rn/src/examples/distortion/index.js
new file mode 100644
index 0000000..1d5d960
--- /dev/null
+++ b/cookbook-rn/src/examples/distortion/index.js
@@ -0,0 +1,66 @@
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+import respondToTouchPosition from "../../HOC/respondToTouchPosition";
+
+const shaders = Shaders.create({
+ vignetteColorSeparationDistortion: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+uniform vec2 mouse;
+uniform float time, amp, freq, moving;
+vec2 lookup (vec2 offset, float amp2) {
+ return mod(
+ uv + amp2 * amp * vec2(
+ cos(freq*(uv.x+offset.x)+time),
+ sin(freq*(uv.y+offset.x)+time))
+ + vec2(
+ moving * time/10.0,
+ 0.0),
+ vec2(1.0));
+}
+void main() {
+ float dist = distance(uv, mouse);
+ float amp2 = pow(1.0 - dist, 2.0);
+ float colorSeparation = 0.02 * mix(amp2, 1.0, 0.5);
+ vec2 orientation = vec2(1.0, 0.0);
+ float a = (1.0-min(0.95, pow(1.8 * distance(uv, mouse), 4.0) +
+ 0.5 * pow(distance(fract(50.0 * uv.y), 0.5), 2.0)));
+ gl_FragColor = vec4(a * vec3(
+ texture2D(t, lookup(colorSeparation * orientation, amp2)).r,
+ texture2D(t, lookup(-colorSeparation * orientation, amp2)).g,
+ texture2D(t, lookup(vec2(0.0), amp2)).b),
+ 1.0);
+}` }
+});
+
+
+const Vignette = timeLoop(({ children: t, time, mouse }) =>
+ );
+
+export default respondToTouchPosition(class Example extends Component {
+ props: { touchPosition: { x: number, y: number } };
+ render() {
+ const { touchPosition: {x, y} } = this.props;
+ return (
+
+
+ {require("../../2VP5osy.jpg")}
+
+
+ );
+ }
+});
diff --git a/cookbook-rn/src/examples/distortion/meta.js b/cookbook-rn/src/examples/distortion/meta.js
new file mode 100644
index 0000000..ca71fa6
--- /dev/null
+++ b/cookbook-rn/src/examples/distortion/meta.js
@@ -0,0 +1,2 @@
+export const title = "Crazy distortion effect on an image";
+export const description = "Vignette color separation distortion + touch responsive";
diff --git a/cookbook-rn/src/examples/gen.sh b/cookbook-rn/src/examples/gen.sh
new file mode 100755
index 0000000..eb00e23
--- /dev/null
+++ b/cookbook-rn/src/examples/gen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+echo "// This file is generated by \`npm run generate-examples\` from index.txt"
+while read ex
+do
+ if [ ! -z $ex ] && [ -d $ex ]
+ then
+ echo "import ${ex}_E from './$ex';";
+ echo "import * as ${ex}_m from './$ex/meta';";
+ echo "export const $ex={ Example: ${ex}_E, ...${ex}_m };"
+ elif [ ! -z _TODO_$ex ] && [ -d _TODO_$ex ]
+ then
+ echo "import * as ${ex}_m from './_TODO_$ex/meta';";
+ echo "export const $ex={ Example: null, ...${ex}_m };"
+ else
+ echo "$ex not found" 1>&2;
+ fi
+done < index.txt;
diff --git a/cookbook-rn/src/examples/glsledit/index.js b/cookbook-rn/src/examples/glsledit/index.js
new file mode 100644
index 0000000..2258112
--- /dev/null
+++ b/cookbook-rn/src/examples/glsledit/index.js
@@ -0,0 +1,94 @@
+//@flow
+import React, { Component } from "react";
+import { View, Text, StyleSheet } from "react-native";
+import { Node, Visitor, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+
+const styles = StyleSheet.create({
+ compileRoot: {
+ flexDirection: "row",
+ },
+ compile: {
+ padding: 6,
+ backgroundColor: "#000",
+ color: "#c22",
+ fontSize: 10,
+ lineHeight: 18,
+ fontFamily: "Courier New",
+ },
+ compileError: {
+ color: "#c22",
+ },
+ compileSuccess: {
+ color: "#2c2",
+ },
+
+});
+
+const Preview = timeLoop(({ frag, visitor, time }) =>
+
+
+ );
+
+class DisplayError extends Component {
+ props: { error: ?string };
+ render() {
+ const { error } = this.props;
+ if (!error) return
+ Compilation success!
+ ;
+ let err = error.message;
+ const i = err.indexOf("ERROR:");
+ if (i!==-1) err = "line "+err.slice(i + 9);
+ return {err};
+ }
+}
+
+export default class Example extends Component {
+ constructor() {
+ super();
+ const visitor = new Visitor();
+ visitor.onSurfaceDrawError = (error: Error) => this.setState({ error });
+ visitor.onSurfaceDrawEnd = () => this.setState({ error: null });
+ this.state = { error: null, visitor };
+ }
+
+ render() {
+ const { frag } = this.props;
+ const { error, visitor } = this.state;
+ return (
+
+
+
+
+ );
+ }
+
+ props: { frag: string };
+ state: { error: ?Error, visitor: Visitor };
+ static defaultProps = { // adapted from http://glslsandbox.com/e#27937.0
+ frag: GLSL`precision highp float;
+varying vec2 uv;
+
+uniform float time;
+
+void main() {
+ float amnt;
+ float nd;
+ vec4 cbuff = vec4(0.0);
+ for(float i=0.0; i<5.0;i++){
+ nd = sin(3.17*0.8*uv.x + (i*0.1+sin(+time)*0.2) + time)*0.8+0.1 + uv.x;
+ amnt = 1.0/abs(nd-uv.y)*0.01;
+ cbuff += vec4(amnt, amnt*0.3 , amnt*uv.y, 90.0);
+ }
+ for(float i=0.0; i<1.0;i++){
+ nd = sin(3.14*2.0*uv.y + i*40.5 + time)*90.3*(uv.y+80.3)+0.5;
+ amnt = 1.0/abs(nd-uv.x)*0.015;
+ cbuff += vec4(amnt*0.2, amnt*0.2 , amnt*uv.x, 1.0);
+ }
+ gl_FragColor = cbuff;
+}
+`
+ };
+}
diff --git a/cookbook-rn/src/examples/glsledit/meta.js b/cookbook-rn/src/examples/glsledit/meta.js
new file mode 100644
index 0000000..52b623e
--- /dev/null
+++ b/cookbook-rn/src/examples/glsledit/meta.js
@@ -0,0 +1,32 @@
+import { StyleSheet } from "react-native";
+export const title = "GLSL live editor";
+import makeTextArea from "../../toolbox/makeTextArea";
+
+const styles = StyleSheet.create({
+ editor: {
+ flex: 1,
+ height: 400,
+ padding: 10,
+ margin: 0,
+ backgroundColor: "#282c34",
+ color: "#ABB2BF",
+ fontSize: 10,
+ lineHeight: 1.5,
+ fontFamily: "Courier New",
+ },
+});
+
+export const overrideStyles = StyleSheet.create({
+ toolbox: {
+ paddingBottom: 0,
+ },
+ field: {
+ paddingVertical: 0,
+ paddingHorizontal: 0,
+ }
+});
+
+export const toolbox = [
+ { prop: "frag",
+ Editor: makeTextArea(styles.editor) }
+];
diff --git a/cookbook-rn/src/examples/gol/index.js b/cookbook-rn/src/examples/gol/index.js
new file mode 100644
index 0000000..589cf31
--- /dev/null
+++ b/cookbook-rn/src/examples/gol/index.js
@@ -0,0 +1,83 @@
+//@flow
+import React from "react";
+import {Backbuffer,Shaders,Node,GLSL,NearestCopy} from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+
+export const shaders = Shaders.create({
+ InitGameOfLife: {
+// returns white or black randomly
+ frag: GLSL`
+precision highp float;
+// i
+varying vec2 uv;
+float random (vec2 uv) {
+ return fract(sin(dot(uv, vec2(12.9898,78.233))) * 43758.5453);
+}
+// i
+void main() {
+ gl_FragColor = vec4(vec3(step(0.5, random(uv))), 1.0);
+}`
+ },
+ GameOfLife: {
+// implement Game Of Life.
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform float size;
+uniform sampler2D t; // the previous world state
+void main() {
+ float prev = step(0.5, texture2D(t, uv).r);
+ float c = 1.0 / size;
+ float sum =
+ step(0.5, texture2D(t, uv + vec2(-1.0, -1.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2(-1.0, 0.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2(-1.0, 1.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2( 0.0, 1.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2( 1.0, 1.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2( 1.0, 0.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2( 1.0, -1.0)*c).r) +
+ step(0.5, texture2D(t, uv + vec2( 0.0, -1.0)*c).r);
+ float next = prev==1.0 && sum >= 2.0 && sum <= 3.0 || sum == 3.0 ? 1.0 : 0.0;
+ gl_FragColor = vec4(vec3(next), 1.0);
+}`
+ }
+});
+
+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));
+ // However, we can conditionally change shader/uniforms,
+ // React reconciliation will preserve the same instance,
+ // and our Game of Life state will get preserved!
+ return tick%refreshEveryTicks===0
+ ? to draw in sync each componentDidUpdate time
+ />
+ : ;
+};
+
+const GameOfLifeLoop = timeLoop(GameOfLife, { refreshRate: 20 });
+
+export default () =>
+
+
+
+
+
diff --git a/cookbook-rn/src/examples/gol/meta.js b/cookbook-rn/src/examples/gol/meta.js
new file mode 100644
index 0000000..9decafb
--- /dev/null
+++ b/cookbook-rn/src/examples/gol/meta.js
@@ -0,0 +1 @@
+export const title = "GameOfLife";
diff --git a/cookbook-rn/src/examples/golglider/glider-gun-64.png b/cookbook-rn/src/examples/golglider/glider-gun-64.png
new file mode 100644
index 0000000..79f3cbc
Binary files /dev/null and b/cookbook-rn/src/examples/golglider/glider-gun-64.png differ
diff --git a/cookbook-rn/src/examples/golglider/index.js b/cookbook-rn/src/examples/golglider/index.js
new file mode 100644
index 0000000..67e017f
--- /dev/null
+++ b/cookbook-rn/src/examples/golglider/index.js
@@ -0,0 +1,37 @@
+//@flow
+import React, { Component } from "react";
+import { Backbuffer, Node, NearestCopy } from "gl-react";
+import { Surface } from "gl-react-native";
+import {shaders} from "../gol";
+import timeLoop from "../../HOC/timeLoop";
+import gliderGunImage from "./glider-gun-64.png";
+
+const GameOfLifeLoop = timeLoop(({ tick, size }) =>
+ , { refreshRate: 20 });
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/examples/golglider/meta.js b/cookbook-rn/src/examples/golglider/meta.js
new file mode 100644
index 0000000..b799ecd
--- /dev/null
+++ b/cookbook-rn/src/examples/golglider/meta.js
@@ -0,0 +1,2 @@
+export const title = "GameOfLife is initialized with a glider texture";
+export const description = "Game of Life init with an image";
diff --git a/cookbook-rn/src/examples/golrot/index.js b/cookbook-rn/src/examples/golrot/index.js
new file mode 100644
index 0000000..9b33fa1
--- /dev/null
+++ b/cookbook-rn/src/examples/golrot/index.js
@@ -0,0 +1,45 @@
+//@flow
+import React from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+import {GameOfLife} from "../gol";
+
+const shaders = Shaders.create({
+ Rotating: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform float angle, scale;
+uniform sampler2D children;
+void main() {
+ mat2 rotation = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
+ vec2 p = (uv - vec2(0.5)) * rotation / scale + vec2(0.5);
+ gl_FragColor =
+ p.x < 0.0 || p.x > 1.0 || p.y < 0.0 || p.y > 1.0
+ ? vec4(0.0)
+ : texture2D(children, p);
+}` }
+});
+
+export const Rotating = ({ angle, scale, children }) =>
+ ;
+
+const RotatingLoop = timeLoop(({ time, children }) => Rotating({
+ angle: (time / 1000) % (2 * Math.PI),
+ scale: 0.6 + 0.15 * Math.cos(time / 500),
+ children,
+}));
+
+const GameOfLifeLoop = timeLoop(GameOfLife, { refreshRate: 5 });
+
+export default () =>
+
+
+
+
+ ;
diff --git a/cookbook-rn/src/examples/golrot/meta.js b/cookbook-rn/src/examples/golrot/meta.js
new file mode 100644
index 0000000..e212fd1
--- /dev/null
+++ b/cookbook-rn/src/examples/golrot/meta.js
@@ -0,0 +1,2 @@
+export const title = "Rotating GameOfLife. 2 loops";
+export const description = "Compose Game of Life with Rotation";
diff --git a/cookbook-rn/src/examples/golrotscu/index.js b/cookbook-rn/src/examples/golrotscu/index.js
new file mode 100644
index 0000000..dfb6aec
--- /dev/null
+++ b/cookbook-rn/src/examples/golrotscu/index.js
@@ -0,0 +1,36 @@
+//@flow
+import React, { Component } from "react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+import {GameOfLife} from "../gol";
+import {Rotating} from "../golrot";
+
+class PureGameOfLife extends Component {
+ shouldComponentUpdate ({ tick }) { // only tick should trigger redraw
+ return tick !== this.props.tick;
+ }
+ render() {
+ return ;
+ }
+}
+
+const RotatingGameOfLife = ({ time }) =>
+
+
+
+
+ ;
+
+export const RotatingGameOfLifeLoop = timeLoop(RotatingGameOfLife);
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/examples/golrotscu/meta.js b/cookbook-rn/src/examples/golrotscu/meta.js
new file mode 100644
index 0000000..9a4bf4e
--- /dev/null
+++ b/cookbook-rn/src/examples/golrotscu/meta.js
@@ -0,0 +1,2 @@
+export const title = "Rotating GameOfLife with sCU";
+export const description = "Single update loop and shouldComponentUpdate";
diff --git a/cookbook-rn/src/examples/gradients/index.js b/cookbook-rn/src/examples/gradients/index.js
new file mode 100644
index 0000000..2ceb108
--- /dev/null
+++ b/cookbook-rn/src/examples/gradients/index.js
@@ -0,0 +1,56 @@
+//@flow
+import React from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+
+const shaders = Shaders.create({
+ gradients: { frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform vec4 colors[3];
+uniform vec2 particles[3];
+void main () {
+ vec4 sum = vec4(0.0);
+ for (int i=0; i<3; i++) {
+ vec4 c = colors[i];
+ vec2 p = particles[i];
+ float d = c.a * smoothstep(0.6, 0.2, distance(p, uv));
+ sum += d * vec4(c.a * c.rgb, c.a);
+ }
+ if (sum.a > 1.0) {
+ sum.rgb /= sum.a;
+ sum.a = 1.0;
+ }
+ gl_FragColor = vec4(sum.a * sum.rgb, 1.0);
+}`}
+});
+
+// Alternative syntax using React stateless function component
+const Gradients = ({ time }) =>
+ ;
+
+const GradientsLoop = timeLoop(Gradients);
+
+export default () =>
+
+
+ ;
+
+// NB: don't abuse the uniforms array:
+// it's not meant to be used with lot of objects.
+// GLSL 1 also don't support variable length in loops.
diff --git a/cookbook-rn/src/examples/gradients/meta.js b/cookbook-rn/src/examples/gradients/meta.js
new file mode 100644
index 0000000..fc34809
--- /dev/null
+++ b/cookbook-rn/src/examples/gradients/meta.js
@@ -0,0 +1,2 @@
+export const title = "Rotating radial gradients";
+export const description = "More advanced animation";
diff --git a/cookbook-rn/src/examples/heart/index.js b/cookbook-rn/src/examples/heart/index.js
new file mode 100644
index 0000000..252ced8
--- /dev/null
+++ b/cookbook-rn/src/examples/heart/index.js
@@ -0,0 +1,69 @@
+//@flow
+import React, { Component } from "react";
+import { TouchableWithoutFeedback } from "react-native";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import {Motion, spring} from "react-motion";
+
+const shaders = Shaders.create({
+ Heart: { // inspired from http://glslsandbox.com/e#29521.0
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D image;
+uniform vec3 color;
+uniform float over, toggle;
+void main() {
+ float scale = 1.0 - 0.1 * over - 0.8 * toggle;
+ vec2 offset = vec2(0.0, -0.3 - 0.1 * over - 0.7 * toggle);
+ vec2 p = scale * (2.0 * uv - 1.0 + offset);
+ float a = atan(p.x, p.y) / ${Math.PI/* \o/ */};
+ float r = length(p);
+ float h = abs(a);
+ float d = (13.0*h - 22.0*h*h + 10.0*h*h*h - 0.3 * (1.0-over))/(6.0-5.0*h);
+ float f = step(r,d) * pow(max(1.0-r/d, 0.0),0.25);
+ vec3 t = texture2D(image, uv).rgb;
+ vec3 c = mix(color * (1.0 + 0.6 * t), t, min(0.8 * over + toggle, 1.0));
+ gl_FragColor = vec4(mix(vec3(1.0), c, f), 1.0);
+}`
+ }
+});
+
+class InteractiveHeart extends Component {
+ state = { over: 0, toggle: 0 };
+ onPressIn = () => this.setState({ over: 1 });
+ onPressOut = () => this.setState({ over: 0 });
+ onPress = () => this.setState({
+ toggle: this.state.toggle ? 0 : 1
+ });
+ render() {
+ const { color, image } = this.props;
+ const { over, toggle } = this.state;
+ return (
+
+
+ { ({ over, toggle }) =>
+
+ }
+
+
+ );
+ }
+}
+
+export default () =>
+ ;
diff --git a/cookbook-rn/src/examples/heart/meta.js b/cookbook-rn/src/examples/heart/meta.js
new file mode 100644
index 0000000..e6ccdda
--- /dev/null
+++ b/cookbook-rn/src/examples/heart/meta.js
@@ -0,0 +1 @@
+export const title = "Heart animation";
diff --git a/cookbook-rn/src/examples/helloblue/index.js b/cookbook-rn/src/examples/helloblue/index.js
new file mode 100644
index 0000000..a38938a
--- /dev/null
+++ b/cookbook-rn/src/examples/helloblue/index.js
@@ -0,0 +1,36 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ helloBlue: {
+ // uniforms are variables from JS. We pipe blue uniform into blue output color
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform float blue;
+void main() {
+ gl_FragColor = vec4(uv.x, uv.y, blue, 1.0);
+}` }
+});
+
+// We can make a that will render the concrete
+export class HelloBlue extends Component {
+ render() {
+ const { blue } = this.props;
+ return ;
+ }
+}
+
+// Our example will pass the slider value to HelloBlue
+export default class Example extends Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+ static defaultProps = { blue: 0.5 };
+}
diff --git a/cookbook-rn/src/examples/helloblue/meta.js b/cookbook-rn/src/examples/helloblue/meta.js
new file mode 100644
index 0000000..f68aae8
--- /dev/null
+++ b/cookbook-rn/src/examples/helloblue/meta.js
@@ -0,0 +1,9 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+
+export const title = "Hello GL blue";
+
+export const toolbox = [
+ { prop: "blue",
+ title: "Blue Color",
+ Editor: makeFloatSlider(0, 1, 0.01) },
+];
diff --git a/cookbook-rn/src/examples/helloblueanim/index.js b/cookbook-rn/src/examples/helloblueanim/index.js
new file mode 100644
index 0000000..1479062
--- /dev/null
+++ b/cookbook-rn/src/examples/helloblueanim/index.js
@@ -0,0 +1,21 @@
+//@flow
+import React, { Component } from "react";
+import { Surface } from "gl-react-native";
+
+// Reuse that previous HelloBlue component to animate it...
+import { HelloBlue } from "../helloblue";
+
+// timeLoop is an utility that animates a component.
+// in a requestAnimationFrame loop and provide a time and tick prop
+import timeLoop from "../../HOC/timeLoop";
+
+export default timeLoop(class Example extends Component {
+ render() {
+ const { time } = this.props;
+ return (
+
+
+
+ );
+ }
+});
diff --git a/cookbook-rn/src/examples/helloblueanim/meta.js b/cookbook-rn/src/examples/helloblueanim/meta.js
new file mode 100644
index 0000000..9d01979
--- /dev/null
+++ b/cookbook-rn/src/examples/helloblueanim/meta.js
@@ -0,0 +1 @@
+export const title = "Hello GL blue animated";
diff --git a/cookbook-rn/src/examples/hellogl/index.js b/cookbook-rn/src/examples/hellogl/index.js
new file mode 100644
index 0000000..2af012a
--- /dev/null
+++ b/cookbook-rn/src/examples/hellogl/index.js
@@ -0,0 +1,34 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+
+// in gl-react you need to statically define "shaders":
+const shaders = Shaders.create({
+ helloGL: {
+// This is our first fragment shader in GLSL language (OpenGL Shading Language)
+// (GLSL code gets compiled and run on the GPU)
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+void main() {
+ gl_FragColor = vec4(uv.x, uv.y, 0.5, 1.0);
+}`
+// the main() function is called FOR EACH PIXELS
+// the varying uv is a vec2 where x and y respectively varying from 0.0 to 1.0.
+// we set in output the pixel color using the vec4(r,g,b,a) format.
+// see [GLSL_ES_Specification_1.0.17](http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf)
+ }
+});
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+
+ );
+// Surface creates the canvas, an area of pixels where you can draw.
+// Node instanciates a "shader program" with the fragment shader defined above.
+ }
+}
diff --git a/cookbook-rn/src/examples/hellogl/meta.js b/cookbook-rn/src/examples/hellogl/meta.js
new file mode 100644
index 0000000..7032e63
--- /dev/null
+++ b/cookbook-rn/src/examples/hellogl/meta.js
@@ -0,0 +1 @@
+export const title = "Hello GL";
diff --git a/cookbook-rn/src/examples/ibex/index.js b/cookbook-rn/src/examples/ibex/index.js
new file mode 100644
index 0000000..e35d034
--- /dev/null
+++ b/cookbook-rn/src/examples/ibex/index.js
@@ -0,0 +1,615 @@
+/**
+ * This celullar automaton is extracted from a game I wrote in 2014 for JS13K:
+ * https://github.com/gre/ibex
+ *
+ * Technical article: http://greweb.me/2014/09/ibex-cellular-automata/
+ */
+
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL, Backbuffer } from "gl-react";
+import { Surface } from "gl-react-native";
+import ndarray from "ndarray";
+import timeLoop from "../../HOC/timeLoop";
+
+const shaders = Shaders.create({
+ IBEXRender: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform vec2 size;
+uniform sampler2D state;
+uniform vec3 CL[9];
+
+float rand(vec2 co){
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+}
+vec3 colorFor (int e) {
+ if(e==0) return CL[0];
+ if(e==1) return CL[1];
+ if(e==2) return CL[2];
+ if(e==3) return CL[3];
+ if(e==4) return CL[4];
+ if(e==5) return CL[5];
+ if(e==6) return CL[6];
+ if(e==7) return CL[7];
+ return CL[8];
+}
+int getState (vec2 pos) {
+ vec2 uv = (floor(pos) + 0.5) / size;
+ bool outOfBound = uv.x<0.0||uv.x>1.0||uv.y<0.0||uv.y>1.0;
+ if (outOfBound) return pos.y < 0.0 ? 1 : 0;
+ float cel = texture2D(state, uv).r;
+ return int(floor(.5 + 9. * cel));
+}
+vec3 stateColorPass (int e, vec2 pos) {
+ return (
+ mix(1.0, rand(pos), 0.05*float(e==1) + 0.2*float(e==8)) +
+ float(e==8) * (
+ step(0.97, rand(pos)) * vec3(3.0, 0.0, 0.0) +
+ step(rand(pos), 0.02) * vec3(1.5, -0.5, 0.5)
+ )
+ ) * colorFor(e);
+}
+void main(){
+ vec2 statePos = uv * size;
+ vec2 statePosFloor = floor(statePos);
+ vec3 stateColor = stateColorPass(getState(statePosFloor), statePosFloor);
+ vec3 c = stateColor;
+ vec2 pixelPos = fract(statePos);
+ vec3 pixelColor = -vec3(0.03) * (pixelPos.x - pixelPos.y);
+ c += pixelColor;
+ gl_FragColor = vec4(c, 1.0);
+}
+`
+ },
+ IBEXLogic: {
+ frag: GLSL`
+#define RAND (S_=vec2(rand(S_), rand(S_+9.))).x
+#define AnyADJ(e) (NW==e||SE==e||NE==e||SW==e||NN==e||SS==e||EE==e||WW==e)
+precision highp float;
+int A = 0;
+int E = 1;
+int F = 2;
+int W = 3;
+int V = 4;
+int S = 5;
+int Al = 6;
+int Ar = 7;
+int G = 8;
+varying vec2 uv;
+uniform vec2 SZ;
+uniform float SD;
+uniform float TI;
+uniform float TS;
+uniform float ST;
+uniform sampler2D state;
+uniform bool RU;
+uniform bool draw;
+uniform ivec2 DP;
+uniform float DR;
+uniform int DO;
+uniform float forestGrowFactor;
+int get (int x_, int y_) {
+ vec2 u = (SZ * uv + vec2(x_, y_)) / SZ;
+ return (u.x < 0.0 || u.x >= 1.0 || u.y < 0.0 || u.y >= 1.0) ? 0 :
+ int(floor(.5 + 9. * texture2D(state, u).r));
+}
+bool between (float f, float a, float b) {
+ return a <= f && f <= b;
+}
+float rand(vec2 co){
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+}
+float grassDistrib (vec2 p) {
+ return mix(
+ rand(vec2(p.x)),
+ 0.5*(1.0+(cos(sin(p.y*0.01 + p.x * 0.05) +
+ (1.0 + 0.3*sin(p.x*0.01)) * p.y * 0.08))),
+ 0.6
+ );
+}
+bool hellTriggerPosition (vec2 p) {
+ if (TS==0.0) return false;
+ float hellTickStart = 800.0;
+ float hellTickInterv = 70.0;
+ float hellSize = 5.0;
+ float dt = TI - TS - hellTickStart;
+ float x = floor(dt / hellTickInterv);
+ float y = (dt - x * hellTickInterv);
+ return distance(vec2(2.0 * (hellSize * x - ST), hellSize * y), p) <= hellSize;
+}
+void main () {
+ vec2 p = uv * SZ;
+ vec2 S_ = p + 0.001 * TI;
+ int NW = get(-1, 1);
+ int NN = get( 0, 1);
+ int NE = get( 1, 1);
+ int WW = get(-1, 0);
+ int CC = get( 0, 0);
+ int EE = get( 1, 0);
+ int SW = get(-1,-1);
+ int SS = get( 0,-1);
+ int SE = get( 1,-1);
+ bool prevIsSolid = CC==E||CC==G||CC==V||CC==S;
+ int r = A;
+ int grassMaxHeight = int(20.0 * pow(grassDistrib(p), 1.3));
+ float rainRelativeTime = mod(TI, 300.0);
+ float volcRelativeTime = mod(TI, 25.0);
+ if (
+ -0.05 * float(NW==W) + -0.40 * float(NN==W) + -0.05 * float(NE==W) +
+ -0.50 * float(WW==W) + -0.50 * float(CC==W) + -0.50 * float(EE==W) +
+ 0.35 * float(SW==F) + 0.90 * float(SS==F) + 0.35 * float(SE==F)
+ >= 0.9 - 0.6 * RAND
+ ||
+ CC == F && RAND < 0.9 && AnyADJ(G)
+ ) {
+ r = F;
+ }
+ if (
+ between(
+ 0.3 * float(NW==W) + 0.9 * float(NN==W) + 0.3 * float(NE==W) +
+ 0.1 * float(WW==W) + -0.3 * float(CC==F) + 0.1 * float(EE==W) +
+ -0.3 * float(SS==F)
+ ,
+ 0.9 - 0.6 * RAND,
+ 1.4 + 0.3 * RAND
+ )
+ ||
+ !prevIsSolid &&
+ RAND < 0.98 &&
+ ( (WW==W||NW==W) && SW==E || (EE==W||NE==W) && SE==E )
+ ||
+ !prevIsSolid &&
+ p.y >= SZ.y-1.0 &&
+ rainRelativeTime < 100.0 &&
+ between(
+ p.x -
+ (rand(vec2(SD*0.7 + TI - rainRelativeTime)) * SZ.x)
+ ,
+ 0.0,
+ 100.0 * rand(vec2(SD + TI - rainRelativeTime))
+ )
+ ||
+ !prevIsSolid && (
+ 0.9 * float(NW==S) + 1.0 * float(NN==S) + 0.9 * float(NE==S) +
+ 0.7 * float(WW==S) + 0.7 * float(EE==S)
+ >= 1.0 - 0.3 * RAND
+ )
+ ) {
+ r = W;
+ }
+ if (CC == E) {
+ if (!(WW==A && EE==A)) r = E;
+ if (
+ RAND < 0.3 && (
+ 1.0 * float(NW==W) + 1.2 * float(NN==W) + 1.0 * float(NE==W) +
+ 0.5 * float(WW==W) + 0.5 * float(EE==W) +
+ 0.3 * float(SW==W) + 0.2 * float(SS==W) + 0.3 * float(SE==W)
+ >= 3.0 - 2.5 * RAND
+ )
+ ||
+ RAND < 0.01 && ( WW==S || NN==S || EE==S )
+ ) {
+ r = S;
+ }
+ if (
+ RAND < 0.01 + 0.02 * smoothstep(500.0, 5000.0, ST + p.x) &&
+ ( int(WW==V) + int(SS==V) + int(EE==V) + int(SE==V) + int(SW==V) > 1 )
+ ) {
+ r = V;
+ }
+ }
+ if (grassMaxHeight > 0) {
+ if (CC == G) {
+ r = G;
+ if (
+ CC == G &&
+ RAND < 0.9 && (
+ AnyADJ(F) ||
+ AnyADJ(V)
+ )) {
+ r = F;
+ }
+ }
+ else if (!prevIsSolid && (AnyADJ(E) || AnyADJ(G) || AnyADJ(S))) {
+ if (RAND < 0.03 * forestGrowFactor &&
+ get(0, -grassMaxHeight) != G && (
+ SS==G && RAND < 0.07 ||
+ SS==E && RAND < 0.02 ||
+ AnyADJ(W) ||
+ AnyADJ(S)
+ )
+ ) {
+ r = G;
+ }
+ }
+ }
+ if ((!prevIsSolid || CC==F) && SS==V) {
+ r = F;
+ }
+ if (CC == V) {
+ r = V;
+ if (
+ NW==W || NN==W || NE==W || EE==W || WW==W
+ ) {
+ r = RAND < 0.8 ? S : E;
+ }
+ if (
+ RAND<0.005 &&
+ ( int(SW==F||SW==V) + int(SS==F||SS==V) + int(SE==F||SE==V) < 2 )
+ ) {
+ r = E;
+ }
+ if (
+ int(NW==S) + int(SE==S) + int(NE==S) + int(SW==S) +
+ int(NN==S) + int(SS==S) + int(EE==S) + int(WW==S)
+ > 1
+ ) {
+ r = RAND < 0.2 ? V : (RAND < 0.8 ? S : E);
+ }
+ }
+ if (prevIsSolid &&
+ p.y <= 2.0 &&
+ volcRelativeTime <= 1.0 &&
+ RAND < 0.3 &&
+ between(
+ p.x -
+ rand(vec2(SD*0.01 + TI - volcRelativeTime)) * SZ.x
+ ,
+ 0.0,
+ 10.0 * rand(vec2(SD*0.07 + TI - volcRelativeTime))
+ )
+ ) {
+ r = V;
+ }
+ if (CC == S) {
+ r = S;
+ if (
+ RAND<0.06 &&
+ ( int(NW==W||NW==S) + int(NN==W||NN==S) + int(NE==W||NE==S) < 1 )
+
+ ||
+ ( EE==F || WW==F || SS==F || SW==F || SE==F )
+ ) {
+ r = E;
+ }
+ if (AnyADJ(V)) {
+ r = RAND < 0.15 ? V : (RAND < 0.6 ? S : E);
+ }
+ }
+ if (r == A) {
+ if (RAND < 0.00001) r = Al;
+ if (RAND < 0.00001) r = Ar;
+ }
+
+ int wind = r==Al ? Al : r == Ar ? Ar : 0;
+ float f =
+(-0.1+0.05*(RAND-0.5)) * float(NW==Ar) + 0.12 * float(NE==Al) +
+-0.65 * float(WW==Ar) + 0.65 * float(EE==Al) +
+-0.1 * float(SW==Ar) + (0.2+0.05*(RAND-0.5)) * float(SE==Al) ;
+
+ if (between(f, 0.4 * RAND, 0.95)) {
+ wind = Al;
+ }
+ else if (between(f, -0.95, -0.4 * RAND)) {
+ wind = Ar;
+ }
+ if (wind != 0) {
+ if (r == A) {
+ r = wind;
+ }
+ else if(r == F) {
+ if (RAND < 0.4) r = wind;
+ }
+ else if (r == W) {
+ if (RAND < 0.1) r = wind;
+ }
+ }
+ if (draw) {
+ vec2 pos = floor(p);
+ if (distance(pos, vec2(DP)) <= DR) {
+ if (DO == W) {
+ if (prevIsSolid && CC!=G) {
+ r = S;
+ }
+ else if (!prevIsSolid && mod(pos.x + pos.y, 2.0)==0.0) {
+ r = W;
+ }
+ }
+ else if (DO == F) {
+ r = prevIsSolid ? V : F;
+ }
+ else {
+ r = DO;
+ }
+ }
+ }
+ if (hellTriggerPosition(p)) {
+ r = prevIsSolid ? V : F;
+ }
+ if (!RU) {
+ if (r == F || r == W|| r == G) r = A;
+ if (r == V || r == S) r = E;
+ }
+ gl_FragColor = vec4(float(r) / 9.0, 0.0, 0.0, 1.0);
+}`
+ }
+});
+
+class IBEXLogic extends Component {
+ state = {
+ seed: Math.random(),
+ };
+ shouldComponentUpdate({ tick }) {
+ return tick !== this.props.tick;
+ }
+ render() {
+ const {
+ size,
+ tick,
+ initialState,
+ forestGrowFactor,
+ waterFactor,
+ fireFactor,
+ } = this.props;
+ const { seed } = this.state;
+ 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 {
+ w = false;
+ }
+ }
+ if (w) {
+ draw = true;
+ 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) {
+ draw = true;
+ drawPosition=[
+ size[0]*Math.random(),
+ 0,
+ ];
+ drawRadius = 4;
+ drawElement = 2;
+ console.log(drawElement, drawPosition, drawPosition);
+ }
+
+ return ;
+ }
+}
+
+var colors = [
+ [0.11, 0.16, 0.23], // 0: air
+ [0.74, 0.66, 0.51], // 1: earth
+ [0.84, 0.17, 0.08], // 2: fire
+ [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)
+];
+
+const IBEXRender = ({ size, children: state }) =>
+ ;
+
+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,
+ };
+ }
+ });
+ }
+
+ render() {
+ const {
+ size,
+ initialState,
+ forestGrowFactor,
+ waterFactor,
+ fireFactor
+ } = this.props;
+ const {
+ tick,
+ } = this.state;
+ return
+
+ ;
+ }
+});
+
+// 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]) {
+ 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 affectColor (buf, i, c) {
+ buf[i] = ~~(256 * c / 9);
+ buf[i+3] = 1;
+ }
+ 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) {
+ if (x >= 0 && x < w && y >= 0 && y < h) {
+ b[x + y * w] = e;
+ }
+ }
+ var K = 26;
+ var x, y, i, k, e;
+ 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)));
+ set(worldPixelBuf, x, y, e);
+ }
+ }
+ var swp = new Uint8Array(worldPixelBuf);
+ var cur = worldPixelBuf;
+ for (k = 0; k < K; ++k) {
+ for (x = startX; x < worldSize[0]; ++x) {
+ for (y = 0; y < worldSize[1]; ++y) {
+ 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;
+ set(swp, x, y, e);
+ }
+ }
+ var tmp = swp;
+ swp = cur;
+ cur = tmp;
+ }
+ if (swp === cur) worldPixelBuf = swp;
+ 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);
+}
+
+const size = [200,200];
+
+export default class Example extends Component {
+ state = {
+ initialState: generate(0, size),
+ };
+ render() {
+ const { forestGrowFactor, fireFactor, waterFactor, speed } = this.props;
+ const { initialState } = this.state;
+ return (
+
+
+
+ );
+ }
+
+ static defaultProps = {
+ speed: 60,
+ forestGrowFactor: 1,
+ fireFactor: 0,
+ waterFactor: 0,
+ };
+}
+
+
+/**
+* Game Rule Interactions.
+*
+* Each interaction use various probability. Some are very rare, some frequent.
+/!\ here air means wind /!\ it is different of empty, the empty space is
+* called "Nothing" aka N)
+*
+* Primary elements: Water, Fire, Earth, Air
+* =======
+* Water + Nothing => fall / slide
+* Fire + Nothing => grow
+* Air + Nothing => move (directional wind)
+* Water + Air => Water is deviated (wind)
+* Fire + Air => Fire decrease
+* Earth + Water => rarely creates Water Source (water infiltration)
+* Earth + Fire => rarely creates Volcano (fire melt ground into lava)
+*
+* Secondary elements: Source, Volcano
+* =========
+* Source + Nothing => creates Water (on bottom).
+* Volcano + Nothing => creates Fire (on top)
+* Volcano + Source => IF source on top of volcano: sometimes creates Ground.
+* OTHERWISE: sometimes creates volcano.
+* Volcano + Water => rarely creates Source.
+* Earth + Volcano => rarely Volcano expand / grow up in the Earth.
+* Earth + Source => rarely Source expand / infiltrate in the Earth.
+* Source + Fire => Source die.
+*
+* Cases where nothing happens:
+* Water + Fire
+* Earth + Nothing
+* Volcano + Fire
+* Volcano + Air
+* Earth + Air
+* Source + Air
+* Source + Water
+*/
diff --git a/cookbook-rn/src/examples/ibex/meta.js b/cookbook-rn/src/examples/ibex/meta.js
new file mode 100644
index 0000000..eaf119f
--- /dev/null
+++ b/cookbook-rn/src/examples/ibex/meta.js
@@ -0,0 +1,18 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+
+export const title = "IBEX (js13k 2014 – greweb)";
+
+export const toolbox = [
+ { prop: "speed",
+ title: (value) => "Simulation Speed ("+value+" FPS)",
+ Editor: makeFloatSlider(1, 60, 1) },
+ { prop: "forestGrowFactor",
+ title: "Forest Grow Factor",
+ Editor: makeFloatSlider(0, 50, 1) },
+ { prop: "waterFactor",
+ title: "Water Factor",
+ Editor: makeFloatSlider(0, 1, 0.01) },
+ { prop: "fireFactor",
+ title: "Volcano Factor",
+ Editor: makeFloatSlider(0, 1, 0.01) },
+];
diff --git a/cookbook-rn/src/examples/index.js b/cookbook-rn/src/examples/index.js
new file mode 100644
index 0000000..0867aba
--- /dev/null
+++ b/cookbook-rn/src/examples/index.js
@@ -0,0 +1,99 @@
+// This file is generated by `npm run generate-examples` from index.txt
+import hellogl_E from './hellogl';
+import * as hellogl_m from './hellogl/meta';
+export const hellogl={ Example: hellogl_E, ...hellogl_m };
+import helloblue_E from './helloblue';
+import * as helloblue_m from './helloblue/meta';
+export const helloblue={ Example: helloblue_E, ...helloblue_m };
+import helloblueanim_E from './helloblueanim';
+import * as helloblueanim_m from './helloblueanim/meta';
+export const helloblueanim={ Example: helloblueanim_E, ...helloblueanim_m };
+import colordisc_E from './colordisc';
+import * as colordisc_m from './colordisc/meta';
+export const colordisc={ Example: colordisc_E, ...colordisc_m };
+import gradients_E from './gradients';
+import * as gradients_m from './gradients/meta';
+export const gradients={ Example: gradients_E, ...gradients_m };
+import diamondcrop_E from './diamondcrop';
+import * as diamondcrop_m from './diamondcrop/meta';
+export const diamondcrop={ Example: diamondcrop_E, ...diamondcrop_m };
+import diamondhello_E from './diamondhello';
+import * as diamondhello_m from './diamondhello/meta';
+export const diamondhello={ Example: diamondhello_E, ...diamondhello_m };
+import diamondanim_E from './diamondanim';
+import * as diamondanim_m from './diamondanim/meta';
+export const diamondanim={ Example: diamondanim_E, ...diamondanim_m };
+import heart_E from './heart';
+import * as heart_m from './heart/meta';
+export const heart={ Example: heart_E, ...heart_m };
+import animated_E from './animated';
+import * as animated_m from './animated/meta';
+export const animated={ Example: animated_E, ...animated_m };
+import saturation_E from './saturation';
+import * as saturation_m from './saturation/meta';
+export const saturation={ Example: saturation_E, ...saturation_m };
+import colorscale_E from './colorscale';
+import * as colorscale_m from './colorscale/meta';
+export const colorscale={ Example: colorscale_E, ...colorscale_m };
+import distortion_E from './distortion';
+import * as distortion_m from './distortion/meta';
+export const distortion={ Example: distortion_E, ...distortion_m };
+import transitions_E from './transitions';
+import * as transitions_m from './transitions/meta';
+export const transitions={ Example: transitions_E, ...transitions_m };
+import glsledit_E from './glsledit';
+import * as glsledit_m from './glsledit/meta';
+export const glsledit={ Example: glsledit_E, ...glsledit_m };
+import paint_E from './paint';
+import * as paint_m from './paint/meta';
+export const paint={ Example: paint_E, ...paint_m };
+import pixeleditor_E from './pixeleditor';
+import * as pixeleditor_m from './pixeleditor/meta';
+export const pixeleditor={ Example: pixeleditor_E, ...pixeleditor_m };
+import blurxy_E from './blurxy';
+import * as blurxy_m from './blurxy/meta';
+export const blurxy={ Example: blurxy_E, ...blurxy_m };
+import blurxydownscale_E from './blurxydownscale';
+import * as blurxydownscale_m from './blurxydownscale/meta';
+export const blurxydownscale={ Example: blurxydownscale_E, ...blurxydownscale_m };
+import blurmulti_E from './blurmulti';
+import * as blurmulti_m from './blurmulti/meta';
+export const blurmulti={ Example: blurmulti_E, ...blurmulti_m };
+import blurmap_E from './blurmap';
+import * as blurmap_m from './blurmap/meta';
+export const blurmap={ Example: blurmap_E, ...blurmap_m };
+import blurmapmouse_E from './blurmapmouse';
+import * as blurmapmouse_m from './blurmapmouse/meta';
+export const blurmapmouse={ Example: blurmapmouse_E, ...blurmapmouse_m };
+import blurmapdyn_E from './blurmapdyn';
+import * as blurmapdyn_m from './blurmapdyn/meta';
+export const blurmapdyn={ Example: blurmapdyn_E, ...blurmapdyn_m };
+import * as blurimgtitle_m from './_TODO_blurimgtitle/meta';
+export const blurimgtitle={ Example: null, ...blurimgtitle_m };
+import gol_E from './gol';
+import * as gol_m from './gol/meta';
+export const gol={ Example: gol_E, ...gol_m };
+import golglider_E from './golglider';
+import * as golglider_m from './golglider/meta';
+export const golglider={ Example: golglider_E, ...golglider_m };
+import golrot_E from './golrot';
+import * as golrot_m from './golrot/meta';
+export const golrot={ Example: golrot_E, ...golrot_m };
+import golrotscu_E from './golrotscu';
+import * as golrotscu_m from './golrotscu/meta';
+export const golrotscu={ Example: golrotscu_E, ...golrotscu_m };
+import mergechannels_E from './mergechannels';
+import * as mergechannels_m from './mergechannels/meta';
+export const mergechannels={ Example: mergechannels_E, ...mergechannels_m };
+import demotunnel_E from './demotunnel';
+import * as demotunnel_m from './demotunnel/meta';
+export const demotunnel={ Example: demotunnel_E, ...demotunnel_m };
+import demodesert_E from './demodesert';
+import * as demodesert_m from './demodesert/meta';
+export const demodesert={ Example: demodesert_E, ...demodesert_m };
+import demodesertcrt_E from './demodesertcrt';
+import * as demodesertcrt_m from './demodesertcrt/meta';
+export const demodesertcrt={ Example: demodesertcrt_E, ...demodesertcrt_m };
+import ibex_E from './ibex';
+import * as ibex_m from './ibex/meta';
+export const ibex={ Example: ibex_E, ...ibex_m };
diff --git a/cookbook-rn/src/examples/index.txt b/cookbook-rn/src/examples/index.txt
new file mode 100644
index 0000000..a732b92
--- /dev/null
+++ b/cookbook-rn/src/examples/index.txt
@@ -0,0 +1,33 @@
+hellogl
+helloblue
+helloblueanim
+colordisc
+gradients
+diamondcrop
+diamondhello
+diamondanim
+heart
+animated
+saturation
+colorscale
+distortion
+transitions
+glsledit
+paint
+pixeleditor
+blurxy
+blurxydownscale
+blurmulti
+blurmap
+blurmapmouse
+blurmapdyn
+blurimgtitle
+gol
+golglider
+golrot
+golrotscu
+mergechannels
+demotunnel
+demodesert
+demodesertcrt
+ibex
diff --git a/cookbook-rn/src/examples/mergechannels/img1.png b/cookbook-rn/src/examples/mergechannels/img1.png
new file mode 100644
index 0000000..da7b26a
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img1.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img2.png b/cookbook-rn/src/examples/mergechannels/img2.png
new file mode 100644
index 0000000..d53d1f1
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img2.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img3.png b/cookbook-rn/src/examples/mergechannels/img3.png
new file mode 100644
index 0000000..e79cc1d
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img3.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img4.png b/cookbook-rn/src/examples/mergechannels/img4.png
new file mode 100644
index 0000000..04aac4d
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img4.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img5.png b/cookbook-rn/src/examples/mergechannels/img5.png
new file mode 100644
index 0000000..bf9f2c6
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img5.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img6.png b/cookbook-rn/src/examples/mergechannels/img6.png
new file mode 100644
index 0000000..0c3f00f
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img6.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img7.png b/cookbook-rn/src/examples/mergechannels/img7.png
new file mode 100644
index 0000000..ff770ee
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img7.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/img8.png b/cookbook-rn/src/examples/mergechannels/img8.png
new file mode 100644
index 0000000..3e6dbdf
Binary files /dev/null and b/cookbook-rn/src/examples/mergechannels/img8.png differ
diff --git a/cookbook-rn/src/examples/mergechannels/index.js b/cookbook-rn/src/examples/mergechannels/index.js
new file mode 100644
index 0000000..874f249
--- /dev/null
+++ b/cookbook-rn/src/examples/mergechannels/index.js
@@ -0,0 +1,55 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ mergeChannels: {
+ frag: GLSL`precision highp float;
+varying vec2 uv;
+uniform sampler2D channels[3];
+float monochrome (vec3 c) {
+ return 0.2125 * c.r + 0.7154 * c.g + 0.0721 * c.b;
+}
+void main() {
+ gl_FragColor = vec4(
+ monochrome(texture2D(channels[0], uv).rgb),
+ monochrome(texture2D(channels[1], uv).rgb),
+ monochrome(texture2D(channels[2], uv).rgb),
+ 1.0
+ );
+}` }
+});
+
+export class MergeChannels extends Component {
+ render() {
+ const { red, green, blue } = this.props;
+ return ;
+ }
+}
+
+export default class Example extends Component {
+ render() {
+ const { red, green, blue } = this.props;
+ return (
+
+
+
+ );
+ }
+
+ static defaultProps = {
+ red: require("./img1.png"),
+ green: require("./img2.png"),
+ blue: require("./img3.png"),
+ };
+}
diff --git a/cookbook-rn/src/examples/mergechannels/meta.js b/cookbook-rn/src/examples/mergechannels/meta.js
new file mode 100644
index 0000000..a7e0a61
--- /dev/null
+++ b/cookbook-rn/src/examples/mergechannels/meta.js
@@ -0,0 +1,31 @@
+import ImagesPicker from "../../toolbox/ImagesPicker";
+export const title = "Merge color channels";
+export const description = "This is a showcase for Array of textures support.";
+
+const imgPicker = {
+ Editor: ImagesPicker,
+ style: { width: 380 },
+ imageStyle: { maxWidth: 42, maxHeight: 42 },
+ images: [
+ require("./img1.png"),
+ require("./img2.png"),
+ require("./img3.png"),
+ require("./img4.png"),
+ require("./img5.png"),
+ require("./img6.png"),
+ require("./img7.png"),
+ require("./img8.png"),
+ ],
+};
+
+export const toolbox = [
+ { prop: "red",
+ title: "red channel",
+ ...imgPicker },
+ { prop: "green",
+ title: "green channel",
+ ...imgPicker },
+ { prop: "blue",
+ title: "blue channel",
+ ...imgPicker },
+];
diff --git a/cookbook-rn/src/examples/paint/index.js b/cookbook-rn/src/examples/paint/index.js
new file mode 100644
index 0000000..a804684
--- /dev/null
+++ b/cookbook-rn/src/examples/paint/index.js
@@ -0,0 +1,74 @@
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+import respondToTouchPosition from "../../HOC/respondToTouchPosition";
+
+const shaders = Shaders.create({
+ paint: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform bool drawing;
+uniform vec4 color;
+uniform vec2 center;
+uniform float brushRadius;
+void main() {
+ if (drawing) {
+ vec2 d = uv - center;
+ if (length(d) < brushRadius) {
+ gl_FragColor = color;
+ }
+ else {
+ discard;
+ }
+ }
+ else {
+ discard;
+ }
+} ` }
+});
+
+export default respondToTouchPosition(class Example extends Component {
+ props: {
+ touching: boolean,
+ touchPosition: { x: number, y: number },
+ }
+
+ state = {
+ color: [ 1, 0, 0, 1 ],
+ };
+
+ componentWillReceiveProps ({ touching }) {
+ const { touching: prevTouching } = this.props;
+ if (!prevTouching && touching) {
+ this.setState({
+ color: [ Math.random(), Math.random(), Math.random(), 1, ],
+ });
+ }
+ }
+
+ render() {
+ const { touching, touchPosition } = this.props;
+ const { color } = this.state;
+ return (
+
+
+
+ );
+ // NB: We also need to explicitely use clear=null
+ // to disable the Node to clear the framebuffer,
+ // and enable preserveDrawingBuffer webgl options.
+ }
+});
diff --git a/cookbook-rn/src/examples/paint/meta.js b/cookbook-rn/src/examples/paint/meta.js
new file mode 100644
index 0000000..e565a27
--- /dev/null
+++ b/cookbook-rn/src/examples/paint/meta.js
@@ -0,0 +1 @@
+export const title = "Painting using discard;";
diff --git a/cookbook-rn/src/examples/pixeleditor/ToolPicker.js b/cookbook-rn/src/examples/pixeleditor/ToolPicker.js
new file mode 100644
index 0000000..09f8898
--- /dev/null
+++ b/cookbook-rn/src/examples/pixeleditor/ToolPicker.js
@@ -0,0 +1,59 @@
+//@flow
+import React, { PureComponent } from "react";
+import { StyleSheet, View, TouchableOpacity, Image } from "react-native";
+
+const styles = StyleSheet.create({
+ tools: {
+ flexDirection: "row",
+ },
+ tool: {
+ borderWidth: 2,
+ marginHorizontal: 10,
+ width: 40,
+ height: 40,
+ },
+ toolSelected: {
+ borderColor: "#f00",
+ },
+});
+
+const imageMapping = {
+ "brush-1": require("./brush-1.png"),
+ "brush-2": require("./brush-2.png"),
+ "brush-4": require("./brush-4.png"),
+ "rubber": require("./rubber.png"),
+ "color-picker": require("./color-picker.png"),
+};
+
+class Tool extends PureComponent {
+ props: {
+ id: string,
+ selected: boolean,
+ onChange: (key: string)=>void,
+ };
+ onPress = () => this.props.onChange(this.props.id);
+ render() {
+ const { id, selected } = this.props;
+ return
+
+ ;
+ }
+}
+
+export default class ToolPicker extends PureComponent {
+ render() {
+ const { tools, value, onChange } = this.props;
+ return
+ {Object.keys(tools).map(key =>
+ )}
+ ;
+ }
+}
diff --git a/cookbook-rn/src/examples/pixeleditor/brush-1.png b/cookbook-rn/src/examples/pixeleditor/brush-1.png
new file mode 100644
index 0000000..bc00345
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/brush-1.png differ
diff --git a/cookbook-rn/src/examples/pixeleditor/brush-2.png b/cookbook-rn/src/examples/pixeleditor/brush-2.png
new file mode 100644
index 0000000..457bd7e
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/brush-2.png differ
diff --git a/cookbook-rn/src/examples/pixeleditor/brush-4.png b/cookbook-rn/src/examples/pixeleditor/brush-4.png
new file mode 100644
index 0000000..c71aecd
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/brush-4.png differ
diff --git a/cookbook-rn/src/examples/pixeleditor/color-picker.png b/cookbook-rn/src/examples/pixeleditor/color-picker.png
new file mode 100644
index 0000000..f9e5c00
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/color-picker.png differ
diff --git a/cookbook-rn/src/examples/pixeleditor/index.js b/cookbook-rn/src/examples/pixeleditor/index.js
new file mode 100644
index 0000000..51d7adb
--- /dev/null
+++ b/cookbook-rn/src/examples/pixeleditor/index.js
@@ -0,0 +1,179 @@
+//@flow
+import React, { PureComponent, Component } from "react";
+import { Shaders, Node, GLSL, Bus } from "gl-react";
+import { Surface } from "gl-react-native";
+import marioPNG from "./mario.png";
+import respondToTouchPosition from "../../HOC/respondToTouchPosition";
+
+type Vec2 = [number,number];
+
+const shaders = Shaders.create({
+ paint: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform vec4 color;
+uniform vec2 size, mouse;
+uniform float brushRadius;
+uniform bool drawing;
+
+void main() {
+ vec2 p = floor(uv * size) / size;
+ if (drawing) {
+ vec2 d = uv - mouse;
+ if (length(d) < brushRadius) {
+ gl_FragColor = color;
+ }
+ else {
+ discard;
+ }
+ }
+ else {
+ discard;
+ }
+}`,
+ },
+ initTexture: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+void main(){
+ gl_FragColor=texture2D(t,uv);
+}`
+ },
+ pixelEditor: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform vec4 color;
+uniform vec2 size, mouse, gridBorder;
+uniform float brushRadius;
+uniform sampler2D t;
+
+void main() {
+ vec2 p = floor(uv * size) / size;
+ vec2 remain = mod(uv * size, vec2(1.0));
+ float m =
+ step(remain.x, 1.0 - gridBorder.x) *
+ step(remain.y, 1.0 - gridBorder.y);
+ float inBrushSize =
+ step(length(p + (0.5 / size) - mouse), brushRadius);
+ vec4 c = mix(texture2D(t, uv), color, 0.6 * inBrushSize);
+ gl_FragColor = vec4(
+ m * c.rgb,
+ mix(1.0, c.a, m));
+}`,
+ }
+});
+
+class Paint extends PureComponent {
+ state = {
+ initialized: false,
+ };
+ componentDidMount() {
+ this.setState({
+ initialized: true,
+ });
+ }
+ render() {
+ const { initialTexture, onPaintNodeRef, ...rest } = this.props;
+ const { initialized } = this.state;
+ return ;
+ }
+}
+
+class PixelEditor extends PureComponent {
+ render() {
+ const { gridBorder, ...rest } = this.props;
+ const { size, brushRadius, mouse, color } = rest;
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+const size = [ 16, 16 ];
+const gridBorder = [ 1/8, 1/8 ];
+const tools = {
+ "brush-1": { brushRadius: 0.55 / 16 },
+ "brush-2": { brushRadius: 1.1 / 16 },
+ "brush-4": { brushRadius: 2.2 / 16 },
+ "rubber": { brushRadius: 4 / 16, forceColor: [0,0,0,0] },
+ "color-picker": { colorPick: true },
+};
+
+const Example = respondToTouchPosition(class extends Component {
+ render() {
+ const { color, toolKey, touching, touchPosition } = this.props;
+ const tool = tools[toolKey];
+ return (
+
+
+
+ );
+ }
+
+ onColorChange = (rgb) => {
+ this.props.setToolState({ color: rgb.concat([ 1 ]) });
+ };
+
+ paintNode: Node;
+ onPaintNodeRef = (ref: Node) => {
+ this.paintNode = ref;
+ }
+
+ colorPick = ([ x, y ]: Vec2) => {
+ x = Math.floor(x * size[0]);
+ y = Math.floor(y * size[1]);
+ const ndarray = this.paintNode.capture(x, y, 1, 1);
+ this.props.setToolState({
+ color: Array.from(ndarray.data).map(n => n / 255),
+ });
+ };
+});
+
+Example.defaultProps = {
+ color: [ 1, 1, 1, 1 ],
+ toolKey: "brush-4",
+};
+
+export default Example;
+
+export {tools};
diff --git a/cookbook-rn/src/examples/pixeleditor/mario.png b/cookbook-rn/src/examples/pixeleditor/mario.png
new file mode 100644
index 0000000..13c57f0
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/mario.png differ
diff --git a/cookbook-rn/src/examples/pixeleditor/meta.js b/cookbook-rn/src/examples/pixeleditor/meta.js
new file mode 100644
index 0000000..778984c
--- /dev/null
+++ b/cookbook-rn/src/examples/pixeleditor/meta.js
@@ -0,0 +1,10 @@
+import ToolPicker from "./ToolPicker";
+import Vec3ColorPicker from "../../toolbox/Vec3ColorPicker";
+import {tools} from ".";
+
+export const title = "Pixel Editor";
+
+export const toolbox = [
+ { prop: "toolKey", Editor: ToolPicker, tools },
+ { prop: "color", Editor: Vec3ColorPicker },
+];
diff --git a/cookbook-rn/src/examples/pixeleditor/rubber.png b/cookbook-rn/src/examples/pixeleditor/rubber.png
new file mode 100644
index 0000000..0c247af
Binary files /dev/null and b/cookbook-rn/src/examples/pixeleditor/rubber.png differ
diff --git a/cookbook-rn/src/examples/saturation/index.js b/cookbook-rn/src/examples/saturation/index.js
new file mode 100644
index 0000000..3254b62
--- /dev/null
+++ b/cookbook-rn/src/examples/saturation/index.js
@@ -0,0 +1,46 @@
+//@flow
+import React, { Component } from "react";
+import { Shaders, Node, GLSL } from "gl-react";
+import { Surface } from "gl-react-native";
+
+const shaders = Shaders.create({
+ Saturate: {
+ frag: GLSL`
+precision highp float;
+varying vec2 uv;
+uniform sampler2D t;
+uniform float contrast, saturation, brightness;
+const vec3 L = vec3(0.2125, 0.7154, 0.0721);
+void main() {
+ vec4 c = texture2D(t, uv);
+ vec3 brt = c.rgb * brightness;
+ gl_FragColor = vec4(mix(
+ vec3(0.5),
+ mix(vec3(dot(brt, L)), brt, saturation),
+ contrast), c.a);
+}`
+ }
+});
+
+export const Saturate = ({ contrast, saturation, brightness, children }) =>
+ ;
+
+export default class Example extends Component {
+ render() {
+ return (
+
+
+ {require("../../uTP9Xfr.jpg")}
+
+
+ );
+ }
+ static defaultProps = {
+ contrast: 1,
+ saturation: 1,
+ brightness: 1,
+ };
+}
diff --git a/cookbook-rn/src/examples/saturation/meta.js b/cookbook-rn/src/examples/saturation/meta.js
new file mode 100644
index 0000000..483bc5b
--- /dev/null
+++ b/cookbook-rn/src/examples/saturation/meta.js
@@ -0,0 +1,14 @@
+import makeFloatSlider from "../../toolbox/makeFloatSlider";
+export const title = "Contrast/Saturation/Brightness example";
+
+export const toolbox = [
+ { prop: "contrast",
+ title: "Contrast",
+ Editor: makeFloatSlider(0, 2, 0.05) },
+ { prop: "saturation",
+ title: "Saturation",
+ Editor: makeFloatSlider(0, 2, 0.05) },
+ { prop: "brightness",
+ title: "Brightness",
+ Editor: makeFloatSlider(0, 2, 0.05) },
+];
diff --git a/cookbook-rn/src/examples/transitions/images.js b/cookbook-rn/src/examples/transitions/images.js
new file mode 100644
index 0000000..3a4881f
--- /dev/null
+++ b/cookbook-rn/src/examples/transitions/images.js
@@ -0,0 +1,17 @@
+
+export default [
+ require("../../wxqlQkh.jpg"),
+ require("../../G2Whuq3.jpg"),
+ require("../../0bUSEBX.jpg"),
+ require("../../giP58XN.jpg"),
+ require("../../iKdXwVm.jpg"),
+ require("../../IvpoR40.jpg"),
+ require("../../zJIxPEo.jpg"),
+ require("../../CKlmtPs.jpg"),
+ require("../../fnMylHI.jpg"),
+ require("../../vGXYiYy.jpg"),
+ require("../../MnOB9Le.jpg"),
+ require("../../YqsZKgc.jpg"),
+ require("../../0BJobQo.jpg"),
+ require("../../Otbz312.jpg")
+];
diff --git a/cookbook-rn/src/examples/transitions/index.js b/cookbook-rn/src/examples/transitions/index.js
new file mode 100644
index 0000000..4a93182
--- /dev/null
+++ b/cookbook-rn/src/examples/transitions/index.js
@@ -0,0 +1,60 @@
+import React, { Component } from "react";
+import { Shaders, Node, LinearCopy, connectSize } from "gl-react";
+import { Surface } from "gl-react-native";
+import timeLoop from "../../HOC/timeLoop";
+import {shadersDefs, randomTransition} from "./transitions";
+const shaders = Shaders.create(shadersDefs);
+
+const Transition = connectSize(
+({ shader, progress, from, to, uniforms, width, height }) =>
+ );
+
+class Slideshow extends Component {
+ state = {
+ index: 0,
+ transition: randomTransition(),
+ };
+ componentWillReceiveProps ({ time, slideDuration, transitionDuration }) {
+ const index = Math.floor(time / (slideDuration + transitionDuration));
+ if (this.state.index !== index) {
+ this.setState({
+ index,
+ transition: randomTransition(),
+ });
+ }
+ }
+ render() {
+ const { slides, slideDuration, transitionDuration, time } = this.props;
+ const { index, transition } = this.state;
+ const totalDuration = slideDuration + transitionDuration;
+ const progress = Math.max(0,
+ (time - index * totalDuration - slideDuration) / transitionDuration);
+ const from = slides[index % slides.length];
+ const to = slides[(index+1) % slides.length];
+ return (
+ progress
+ ?
+ : {from}
+ );
+ }
+}
+const SlideshowLoop = timeLoop(Slideshow);
+
+import images from "./images";
+export default () =>
+
+
+
diff --git a/cookbook-rn/src/examples/transitions/meta.js b/cookbook-rn/src/examples/transitions/meta.js
new file mode 100644
index 0000000..4700375
--- /dev/null
+++ b/cookbook-rn/src/examples/transitions/meta.js
@@ -0,0 +1,2 @@
+export const title = "GLSL transitions between images";
+export const description = "using transitions.glsl.io";
diff --git a/cookbook-rn/src/examples/transitions/transitions.js b/cookbook-rn/src/examples/transitions/transitions.js
new file mode 100644
index 0000000..2c35427
--- /dev/null
+++ b/cookbook-rn/src/examples/transitions/transitions.js
@@ -0,0 +1,122 @@
+import GlslTransitions from "glsl-transitions";
+import {GLSL} from "gl-react";
+
+const byName = {};
+GlslTransitions.forEach(function (t) {
+ byName[t.name] = t;
+});
+const transitions = [
+ [ "cube", function() {
+ return { persp: 0.9 - Math.random()*Math.random(), unzoom: Math.random()*Math.random() };
+ } ],
+ "undulating burn out",
+ [ "CrossZoom", function() {
+ return { strength: 0.5 * Math.random() };
+ } ],
+ "glitch displace",
+ [ "Mosaic", function() {
+ let dx = Math.round(Math.random() * 6 - 3), dy = Math.round(Math.random() * 6 - 3);
+ if (dx===0 && dy===0) dy = -1;
+ return { endx: dx, endy: dy };
+ } ],
+ [ "DoomScreenTransition", function() {
+ return {
+ barWidth: Math.round(6 + 20 * Math.random()),
+ amplitude: 2 * Math.random(),
+ noise: 0.5 * Math.random(),
+ frequency: Math.random()
+ };
+ } ],
+ [ "colourDistance", function() {
+ return { interpolationPower: 6 * Math.random() };
+ } ],
+ "swap",
+ [ "doorway", function() {
+ return { perspective: Math.random() * Math.random(), depth: 1 + 10 * Math.random() * Math.random() };
+ } ],
+ "Star Wipe",
+ "pinwheel",
+ "SimpleFlip",
+ "TilesScanline",
+ "Dreamy",
+ "Swirl",
+ "burn",
+ "Radial",
+ [ "ripple", function() {
+ return {
+ amplitude: 200 * Math.random(),
+ speed: 200 * Math.random()
+ };
+ } ],
+ "morph",
+ ["ButterflyWaveScrawler", function() {
+ return {
+ amplitude: Math.random(),
+ waves: 50 * Math.random() * Math.random(),
+ colorSeparation: 0.8 * Math.random() * Math.random()
+ };
+ } ],
+ [ "flash", function() {
+ return { flashIntensity: 4 * Math.random() };
+ } ],
+ [ "randomsquares", function() {
+ const size = Math.round(4 + 20 * Math.random());
+ return {
+ size: [ size, size ],
+ smoothness: Math.random()
+ };
+ } ],
+ [ "flyeye", function() {
+ return {
+ size: Math.random() * Math.random(),
+ zoom: 200 * Math.random() * Math.random(),
+ colorSeparation: 0.8 * Math.random() * Math.random()
+ };
+ } ],
+ "squeeze",
+ [ "directionalwipe", function() {
+ const angle = Math.random() * 2 * Math.PI;
+ return {
+ direction: [ Math.cos(angle), Math.sin(angle) ]
+ };
+ } ],
+ "circleopen",
+ [ "wind", function() {
+ return { size: 0.1+0.2 * Math.random() };
+ } ]
+].map(function (obj) {
+ let name, genUniforms;
+ if (typeof obj === "string")
+ name = obj;
+ else {
+ name = obj[0];
+ genUniforms = obj[1];
+ }
+ if (!(name in byName)) throw new Error("no transition called "+name);
+ const t = byName[name];
+ return {
+ transition: t,
+ name: name,
+ genUniforms: function() {
+ return genUniforms ? {
+ ...t.uniforms,
+ ...genUniforms()
+ } : t.uniforms;
+ }
+ };
+});
+
+export function randomTransition() {
+ const i = Math.floor(Math.random() * transitions.length);
+ const t = transitions[i];
+ const uniforms = t.genUniforms ? t.genUniforms() : {};
+ return {
+ name: t.name,
+ uniforms: uniforms
+ };
+}
+
+export const shadersDefs = {};
+transitions.forEach(function (o) {
+ shadersDefs[o.name] = { frag: GLSL`${o.transition.glsl}` };
+});
diff --git a/cookbook-rn/src/fnMylHI.jpg b/cookbook-rn/src/fnMylHI.jpg
new file mode 100644
index 0000000..9c5bfe2
Binary files /dev/null and b/cookbook-rn/src/fnMylHI.jpg differ
diff --git a/cookbook-rn/src/giP58XN.jpg b/cookbook-rn/src/giP58XN.jpg
new file mode 100644
index 0000000..79cb956
Binary files /dev/null and b/cookbook-rn/src/giP58XN.jpg differ
diff --git a/cookbook-rn/src/iKdXwVm.jpg b/cookbook-rn/src/iKdXwVm.jpg
new file mode 100644
index 0000000..1a73177
Binary files /dev/null and b/cookbook-rn/src/iKdXwVm.jpg differ
diff --git a/cookbook-rn/src/iPKTONG.jpg b/cookbook-rn/src/iPKTONG.jpg
new file mode 100644
index 0000000..6462178
Binary files /dev/null and b/cookbook-rn/src/iPKTONG.jpg differ
diff --git a/cookbook-rn/src/index.js b/cookbook-rn/src/index.js
new file mode 100644
index 0000000..9ace719
--- /dev/null
+++ b/cookbook-rn/src/index.js
@@ -0,0 +1,25 @@
+//@flow
+import React from "react";
+import {
+ NavigationProvider,
+ StackNavigation,
+} from "@exponent/ex-navigation";
+import Router from "./Router";
+
+export default class App extends React.Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/k9Eview.jpg b/cookbook-rn/src/k9Eview.jpg
new file mode 100644
index 0000000..986ea17
Binary files /dev/null and b/cookbook-rn/src/k9Eview.jpg differ
diff --git a/cookbook-rn/src/logo.png b/cookbook-rn/src/logo.png
new file mode 100755
index 0000000..a446c96
Binary files /dev/null and b/cookbook-rn/src/logo.png differ
diff --git a/cookbook-rn/src/makeExample.js b/cookbook-rn/src/makeExample.js
new file mode 100644
index 0000000..183f544
--- /dev/null
+++ b/cookbook-rn/src/makeExample.js
@@ -0,0 +1,114 @@
+//@flow
+import React from "react";
+import {
+ StyleSheet,
+ View,
+ ScrollView,
+ Text,
+} from "react-native";
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ backgroundColor: "#fff",
+ },
+ container: {
+ flexDirection: "column",
+ justifyContent: "space-around",
+ },
+ header: {
+
+ },
+ description: {
+
+ },
+ rendering: {
+ alignSelf: "center",
+ // FIXME might do the background color for showing opacity.
+ },
+ toolbox: {
+ paddingBottom: 10,
+ flexDirection: "column",
+ },
+ toolboxTitle: {
+ padding: 0,
+ marginVertical: 4,
+ },
+ field: {
+ flexDirection: "column",
+ paddingVertical: 5,
+ paddingHorizontal: 10,
+ },
+ fieldValue: {
+ flexDirection: "row",
+ },
+});
+
+export default ({
+ Example,
+ title,
+ description,
+ toolbox,
+ ToolboxFooter,
+ overrideStyles = {},
+}, id) => class extends React.Component {
+ static displayName = id;
+ static route = {
+ navigationBar: {
+ title,
+ // TODO: use renderRight to have bg modes, like in Atom image-viewer // renderRight: (route, props) => ...
+ },
+ };
+ state = {
+ ...Example.defaultProps,
+ };
+ render() {
+ const { state } = this;
+ const props = {
+ setToolState: this.setState,
+ ...state,
+ };
+ return (
+
+
+ { description ?
+
+ {description}
+
+ : null }
+
+
+
+
+
+ {(toolbox || []).map((field, i) =>
+
+ { field.title
+ ? {
+ typeof field.title==="function"
+ ? field.title(props[field.prop])
+ : field.title
+ }
+ : null }
+
+ { field.Editor
+ ? {
+ this.setState({
+ [field.prop]: value
+ });
+ }}
+ />
+ : null }
+
+ )}
+ { ToolboxFooter
+ ?
+ : null }
+
+
+ );
+ }
+};
diff --git a/cookbook-rn/src/toolbox/ImagesPicker.js b/cookbook-rn/src/toolbox/ImagesPicker.js
new file mode 100755
index 0000000..d410a10
--- /dev/null
+++ b/cookbook-rn/src/toolbox/ImagesPicker.js
@@ -0,0 +1,59 @@
+//@flow
+import React, { PureComponent, Component } from "react";
+import { Image, View, TouchableOpacity } from "react-native";
+
+class ImagePickable extends PureComponent {
+ props: {
+ style: any,
+ src: *,
+ selected: boolean,
+ onChange: (src: *)=>void,
+ };
+ onPress = () => this.props.onChange(this.props.src);
+ render() {
+ const { src, selected, style } = this.props;
+ return
+
+ ;
+ }
+}
+
+export default class ImagesPicker extends Component {
+ props: {
+ imageStyle?: any,
+ style?: any,
+ value: string,
+ images: Array,
+ onChange: (c: string)=>any,
+ };
+ render() {
+ const {value, onChange, images, style, imageStyle} = this.props;
+ return (
+
+ {images.map(src =>
+ )}
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/toolbox/StaticBlurMap.js b/cookbook-rn/src/toolbox/StaticBlurMap.js
new file mode 100755
index 0000000..b5e8d79
--- /dev/null
+++ b/cookbook-rn/src/toolbox/StaticBlurMap.js
@@ -0,0 +1,20 @@
+//@flow
+import React, { Component } from "react";
+import ImagesPicker from "./ImagesPicker";
+const images = [
+ require("../SzbbUvX.jpg"),
+ require("../0PkQEk1.jpg"),
+ require("../z2CQHpg.jpg"),
+ require("../k9Eview.jpg"),
+ require("../wh0On3P.jpg"),
+];
+export default class StaticBlurMap extends Component {
+ static images = images;
+ render() {
+ return ;
+ }
+}
diff --git a/cookbook-rn/src/toolbox/Vec3ColorPicker.js b/cookbook-rn/src/toolbox/Vec3ColorPicker.js
new file mode 100755
index 0000000..3f38601
--- /dev/null
+++ b/cookbook-rn/src/toolbox/Vec3ColorPicker.js
@@ -0,0 +1,67 @@
+//@flow
+import React, { Component } from "react";
+import { Slider, StyleSheet, View, PixelRatio } from "react-native";
+
+export type Vec3 = [number,number,number];
+
+const styles = StyleSheet.create({
+ root: {
+ flexDirection: "row",
+ flex: 1,
+ alignItems: "center",
+ },
+ slider: {
+ flex: 1,
+ marginHorizontal: 8,
+ },
+ preview: {
+ width: 20,
+ height: 20,
+ borderRadius: 10,
+ borderWidth: 1 / PixelRatio.get(),
+ },
+});
+
+export default class Vec3ColorPicker extends Component {
+ props: {
+ compact?: boolean,
+ value: Vec3,
+ onChange: (c: Vec3)=>any,
+ };
+ render() {
+ const { value, onChange } = this.props;
+ let [ r, g, b ] = value||[];
+ const step = 0.01;
+ return (
+
+ Math.floor(v*255))})`,
+ borderColor: `rgb(${[r,g,b].map(v => Math.floor(0.8*v*255))})`
+ }
+ ]}
+ />
+ onChange([ r, g, b ])}
+ />
+ onChange([ r, g, b ])}
+ />
+ onChange([ r, g, b ])}
+ />
+
+ );
+ }
+}
diff --git a/cookbook-rn/src/toolbox/makeFloatSlider.js b/cookbook-rn/src/toolbox/makeFloatSlider.js
new file mode 100755
index 0000000..c3e3cfb
--- /dev/null
+++ b/cookbook-rn/src/toolbox/makeFloatSlider.js
@@ -0,0 +1,21 @@
+//@flow
+import React, { Component } from "react";
+import { Slider } from "react-native";
+
+export default (min: number=0, max: number=1, step?: number) => class FloatSlider extends Component {
+ props: {
+ value: number,
+ onChange: (c: number)=>any,
+ };
+ render() {
+ const { onChange, value } = this.props;
+ return ;
+ }
+};
diff --git a/cookbook-rn/src/toolbox/makeSelect.js b/cookbook-rn/src/toolbox/makeSelect.js
new file mode 100755
index 0000000..a5af548
--- /dev/null
+++ b/cookbook-rn/src/toolbox/makeSelect.js
@@ -0,0 +1,25 @@
+//@flow
+import React, { Component } from "react";
+import { Picker } from "react-native";
+
+const styles = {
+ root: {
+ flex: 1,
+ },
+};
+
+export default (choices: Array<{ key: string, label: string }>) => class Select extends Component {
+ props: {
+ value: string,
+ onChange: (c: string)=>any,
+ };
+ render() {
+ const {value, onChange} = this.props;
+ return (
+
+ {choices.map(({ key, label }) =>
+ )}
+
+ );
+ }
+};
diff --git a/cookbook-rn/src/toolbox/makeTextArea.js b/cookbook-rn/src/toolbox/makeTextArea.js
new file mode 100755
index 0000000..763b44b
--- /dev/null
+++ b/cookbook-rn/src/toolbox/makeTextArea.js
@@ -0,0 +1,23 @@
+//@flow
+import React, { Component } from "react";
+import { TextInput } from "react-native";
+
+export default (style: any) => class TextArea extends Component {
+ props: {
+ value: string,
+ onChange: (c: string)=>any,
+ };
+ render() {
+ const { onChange, value } = this.props;
+ return (
+
+ );
+ }
+};
diff --git a/cookbook-rn/src/uTP9Xfr.jpg b/cookbook-rn/src/uTP9Xfr.jpg
new file mode 100644
index 0000000..db4ab4e
Binary files /dev/null and b/cookbook-rn/src/uTP9Xfr.jpg differ
diff --git a/cookbook-rn/src/vGXYiYy.jpg b/cookbook-rn/src/vGXYiYy.jpg
new file mode 100644
index 0000000..22bc656
Binary files /dev/null and b/cookbook-rn/src/vGXYiYy.jpg differ
diff --git a/cookbook-rn/src/wh0On3P.jpg b/cookbook-rn/src/wh0On3P.jpg
new file mode 100644
index 0000000..d0fc40c
Binary files /dev/null and b/cookbook-rn/src/wh0On3P.jpg differ
diff --git a/cookbook-rn/src/wxqlQkh.jpg b/cookbook-rn/src/wxqlQkh.jpg
new file mode 100644
index 0000000..86ac7ca
Binary files /dev/null and b/cookbook-rn/src/wxqlQkh.jpg differ
diff --git a/cookbook-rn/src/z2CQHpg.jpg b/cookbook-rn/src/z2CQHpg.jpg
new file mode 100644
index 0000000..ba1ed7f
Binary files /dev/null and b/cookbook-rn/src/z2CQHpg.jpg differ
diff --git a/cookbook-rn/src/zJIxPEo.jpg b/cookbook-rn/src/zJIxPEo.jpg
new file mode 100644
index 0000000..4920b9d
Binary files /dev/null and b/cookbook-rn/src/zJIxPEo.jpg differ
diff --git a/cookbook/API.json b/cookbook/API.json
index a032bff..f446d00 100755
--- a/cookbook/API.json
+++ b/cookbook/API.json
@@ -665,7 +665,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L161-L550"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L161-L550"
},
"kind": "class",
"name": "Surface",
@@ -1937,7 +1937,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L286-L289"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L286-L289"
},
"params": [
{
@@ -2246,7 +2246,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L298-L301"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L298-L301"
},
"params": [
{
@@ -2575,7 +2575,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L308-L311"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L308-L311"
},
"memberof": "Surface",
"scope": "instance",
@@ -2738,7 +2738,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L319-L321"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L319-L321"
},
"memberof": "Surface",
"scope": "instance",
@@ -2855,7 +2855,7 @@
},
"file": "packages/gl-react/src/createSurface.js",
"path": "packages/gl-react/src/createSurface.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/createSurface.js#L329-L331"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/createSurface.js#L329-L331"
},
"memberof": "Surface",
"scope": "instance",
@@ -3155,7 +3155,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L295-L955"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L295-L955"
},
"properties": [
{
@@ -3935,7 +3935,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L459-L477"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L459-L477"
},
"name": "capture",
"kind": "function",
@@ -4088,7 +4088,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L484-L489"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L484-L489"
},
"kind": "function",
"name": "redraw",
@@ -4195,7 +4195,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L496-L498"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L496-L498"
},
"kind": "function",
"name": "flush",
@@ -4314,7 +4314,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L108-L149"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L108-L149"
},
"kind": "namespace",
"name": "Shaders",
@@ -4377,7 +4377,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L122-L138"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L122-L138"
},
"memberof": "Shaders",
"params": [
@@ -4623,7 +4623,7 @@
},
"file": "packages/gl-react/src/LinearCopy.js",
"path": "packages/gl-react/src/LinearCopy.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/LinearCopy.js#L14-L24"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/LinearCopy.js#L14-L24"
},
"properties": [
{
@@ -4795,7 +4795,7 @@
},
"file": "packages/gl-react/src/NearestCopy.js",
"path": "packages/gl-react/src/NearestCopy.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/NearestCopy.js#L14-L25"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/NearestCopy.js#L14-L25"
},
"properties": [
{
@@ -5310,7 +5310,7 @@
},
"file": "packages/gl-react/src/Bus.js",
"path": "packages/gl-react/src/Bus.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Bus.js#L44-L201"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Bus.js#L44-L201"
},
"properties": [
{
@@ -5683,7 +5683,7 @@
},
"file": "packages/gl-react/src/Bus.js",
"path": "packages/gl-react/src/Bus.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Bus.js#L154-L157"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Bus.js#L154-L157"
},
"name": "capture",
"kind": "function",
@@ -5836,7 +5836,7 @@
},
"file": "packages/gl-react/src/Bus.js",
"path": "packages/gl-react/src/Bus.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Bus.js#L169-L171"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Bus.js#L169-L171"
},
"kind": "function",
"name": "redraw",
@@ -6059,7 +6059,7 @@
},
"file": "packages/gl-react/src/connectSize.js",
"path": "packages/gl-react/src/connectSize.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/connectSize.js#L18-L56"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/connectSize.js#L18-L56"
},
"kind": "function",
"name": "connectSize",
@@ -6434,7 +6434,7 @@
},
"file": "packages/gl-react/src/GLSL.js",
"path": "packages/gl-react/src/GLSL.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/GLSL.js#L26-L32"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/GLSL.js#L26-L32"
},
"returns": [
{
@@ -6770,7 +6770,7 @@
},
"file": "packages/gl-react/src/GLSL.js",
"path": "packages/gl-react/src/GLSL.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/GLSL.js#L7-L7"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/GLSL.js#L7-L7"
},
"name": "GLSLCode",
"kind": "typedef",
@@ -6925,7 +6925,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L44-L46"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L44-L46"
},
"examples": [
{
@@ -7067,7 +7067,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L15-L17"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L15-L17"
},
"examples": [
{
@@ -7258,7 +7258,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L51-L53"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L51-L53"
},
"name": "ShadersSheet",
"kind": "typedef",
@@ -7304,7 +7304,7 @@
},
"file": "packages/gl-react/src/Shaders.js",
"path": "packages/gl-react/src/Shaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Shaders.js#L24-L27"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Shaders.js#L24-L27"
},
"name": "ShaderIdentifier",
"kind": "typedef",
@@ -8182,7 +8182,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L162-L164"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L162-L164"
},
"name": "Uniforms",
"kind": "typedef",
@@ -8466,7 +8466,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L69-L72"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L69-L72"
},
"name": "TextureOptions",
"kind": "typedef",
@@ -8804,7 +8804,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L49-L49"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L49-L49"
},
"name": "Interpolation",
"kind": "typedef",
@@ -9134,7 +9134,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L59-L62"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L59-L62"
},
"name": "WrapMode",
"kind": "typedef",
@@ -9193,7 +9193,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L99-L102"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L99-L102"
},
"name": "BlendFuncSrcDst",
"kind": "typedef",
@@ -10223,7 +10223,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L94-L94"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L94-L94"
},
"name": "BlendFunc",
"kind": "typedef",
@@ -10326,7 +10326,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L117-L119"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L117-L119"
},
"name": "Clear",
"kind": "typedef",
@@ -10498,7 +10498,7 @@
},
"file": "packages/gl-react/src/Node.js",
"path": "packages/gl-react/src/Node.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Node.js#L107-L112"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Node.js#L107-L112"
},
"name": "Vec4",
"kind": "typedef",
@@ -10653,7 +10653,7 @@
},
"file": "packages/gl-react/flow/ndarray.js",
"path": "packages/gl-react/flow/ndarray.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/flow/ndarray.js#L7-L13"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/flow/ndarray.js#L7-L13"
},
"name": "NDArray",
"kind": "typedef",
@@ -10990,7 +10990,7 @@
},
"file": "packages/gl-react/flow/gl-texture2d.js",
"path": "packages/gl-react/flow/gl-texture2d.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/flow/gl-texture2d.js#L7-L15"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/flow/gl-texture2d.js#L7-L15"
},
"name": "Texture",
"kind": "typedef",
@@ -11299,7 +11299,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L10-L51"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L10-L51"
},
"name": "TextureLoader",
"kind": "class",
@@ -11342,7 +11342,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L15-L15"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L15-L15"
},
"properties": [
{
@@ -11457,7 +11457,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L20-L22"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L20-L22"
},
"name": "constructor",
"kind": "function",
@@ -11568,7 +11568,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L27-L27"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L27-L27"
},
"name": "dispose",
"kind": "member",
@@ -11675,7 +11675,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L32-L32"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L32-L32"
},
"name": "canLoad",
"kind": "member",
@@ -11791,7 +11791,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L37-L37"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L37-L37"
},
"name": "get",
"kind": "member",
@@ -11917,7 +11917,7 @@
},
"file": "packages/gl-react/src/TextureLoader.js",
"path": "packages/gl-react/src/TextureLoader.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoader.js#L44-L50"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoader.js#L44-L50"
},
"name": "load",
"kind": "function",
@@ -12064,7 +12064,7 @@
},
"file": "packages/gl-react/src/Visitors.js",
"path": "packages/gl-react/src/Visitors.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitors.js#L10-L28"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitors.js#L10-L28"
},
"kind": "namespace",
"name": "Visitors",
@@ -12103,7 +12103,7 @@
},
"file": "packages/gl-react/src/Visitors.js",
"path": "packages/gl-react/src/Visitors.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitors.js#L14-L16"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitors.js#L14-L16"
},
"memberof": "Visitors",
"name": "add",
@@ -12167,7 +12167,7 @@
},
"file": "packages/gl-react/src/Visitors.js",
"path": "packages/gl-react/src/Visitors.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitors.js#L20-L23"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitors.js#L20-L23"
},
"memberof": "Visitors",
"name": "remove",
@@ -12331,7 +12331,7 @@
},
"file": "packages/gl-react/src/TextureLoaders.js",
"path": "packages/gl-react/src/TextureLoaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoaders.js#L14-L33"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoaders.js#L14-L33"
},
"kind": "namespace",
"name": "TextureLoaders",
@@ -12421,7 +12421,7 @@
},
"file": "packages/gl-react/src/TextureLoaders.js",
"path": "packages/gl-react/src/TextureLoaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoaders.js#L19-L21"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoaders.js#L19-L21"
},
"memberof": "TextureLoaders",
"name": "add",
@@ -12553,7 +12553,7 @@
},
"file": "packages/gl-react/src/TextureLoaders.js",
"path": "packages/gl-react/src/TextureLoaders.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/TextureLoaders.js#L26-L29"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/TextureLoaders.js#L26-L29"
},
"memberof": "TextureLoaders",
"name": "remove",
@@ -12638,7 +12638,7 @@
},
"file": "packages/gl-react/src/VisitorLogger.js",
"path": "packages/gl-react/src/VisitorLogger.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/VisitorLogger.js#L20-L100"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/VisitorLogger.js#L20-L100"
},
"name": "VisitorLogger",
"augments": [
@@ -12686,7 +12686,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L24-L64"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L24-L64"
},
"name": "Visitor",
"kind": "class",
@@ -12718,7 +12718,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L28-L28"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L28-L28"
},
"name": "onSurfaceMount",
"kind": "function",
@@ -12778,7 +12778,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L32-L32"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L32-L32"
},
"name": "onSurfaceUnmount",
"kind": "function",
@@ -12838,7 +12838,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L36-L36"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L36-L36"
},
"name": "onSurfaceGLContextChange",
"kind": "function",
@@ -12910,7 +12910,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L39-L39"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L39-L39"
},
"name": "onSurfaceDrawSkipped",
"kind": "function",
@@ -12970,7 +12970,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L42-L42"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L42-L42"
},
"name": "onSurfaceDrawStart",
"kind": "function",
@@ -13030,7 +13030,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L45-L45"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L45-L45"
},
"name": "onSurfaceDrawError",
"kind": "function",
@@ -13090,7 +13090,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L48-L48"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L48-L48"
},
"name": "onSurfaceDrawEnd",
"kind": "function",
@@ -13150,7 +13150,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L51-L51"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L51-L51"
},
"name": "onNodeDrawSkipped",
"kind": "function",
@@ -13210,7 +13210,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L54-L54"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L54-L54"
},
"name": "onNodeDrawStart",
"kind": "function",
@@ -13270,7 +13270,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L57-L57"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L57-L57"
},
"name": "onNodeSyncDeps",
"kind": "function",
@@ -13384,7 +13384,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L60-L60"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L60-L60"
},
"name": "onNodeDraw",
"kind": "function",
@@ -13459,7 +13459,7 @@
},
"file": "packages/gl-react/src/Visitor.js",
"path": "packages/gl-react/src/Visitor.js",
- "github": "https://github.com/gre/gl-react/blob/53b19cdbb6dac428b7f2100de0bd2870a6870b78/packages/gl-react/src/Visitor.js#L63-L63"
+ "github": "https://github.com/gre/gl-react/blob/d0bc4db823dc913a2ab745107dc425a6767faabf/packages/gl-react/src/Visitor.js#L63-L63"
},
"name": "onNodeDrawEnd",
"kind": "function",
diff --git a/cookbook/src/HOC/timeLoop.js b/cookbook/src/HOC/timeLoop.js
index 8db07f5..b0dbb97 100755
--- a/cookbook/src/HOC/timeLoop.js
+++ b/cookbook/src/HOC/timeLoop.js
@@ -42,9 +42,9 @@ export default (
{...this.state}
/>;
}
- };
+ }
hoistNonReactStatics(TL, C);
return TL;
-}
+};
diff --git a/cookbook/src/examples/blurmapdyn/meta.js b/cookbook/src/examples/blurmapdyn/meta.js
index 6436dfa..750e33f 100755
--- a/cookbook/src/examples/blurmapdyn/meta.js
+++ b/cookbook/src/examples/blurmapdyn/meta.js
@@ -1,6 +1,6 @@
import markdown from "../../markdown";
import makeFloatSlider from "../../toolbox/makeFloatSlider";
-export const title = "Blur with intensity map & multi-pass";
+export const title = "Blur with dynamic shader mapping";
export const desc = markdown`
Any arbitrary shader can be used as a blur map!
`;
diff --git a/cookbook/src/examples/diamondhello/index.js b/cookbook/src/examples/diamondhello/index.js
index 54d19fe..1d579fc 100755
--- a/cookbook/src/examples/diamondhello/index.js
+++ b/cookbook/src/examples/diamondhello/index.js
@@ -7,13 +7,11 @@ import { HelloBlue } from "../helloblue";
export default class Example extends Component {
render() {
return (
-
-
-
-
-
-
-
+
+
+
+
+
);
}
-};
+}
diff --git a/package.json b/package.json
index ced3589..80e76eb 100644
--- a/package.json
+++ b/package.json
@@ -26,5 +26,8 @@
"eslint-plugin-react": "^6.7.1",
"flow-copy-source": "^1.1.0"
},
- "version": "3.0.0-alpha1"
+ "version": "3.0.0-alpha1",
+ "devDependencies": {
+ "flow-bin": "^0.37.4"
+ }
}
diff --git a/packages/gl-react-native/package.json b/packages/gl-react-native/package.json
index d51f26f..cac61c9 100644
--- a/packages/gl-react-native/package.json
+++ b/packages/gl-react-native/package.json
@@ -23,10 +23,10 @@
"peerDependencies": {
"react": "*",
"react-native": "*",
+ "exponent": "*",
"gl-react": "*"
},
"dependencies": {
- "exponent": "^11.0.0-rc1",
"invariant": "^2.2.1"
}
}
diff --git a/packages/gl-react-native/src/ExponentTextureLoader.js b/packages/gl-react-native/src/ExponentTextureLoader.js
index 5b5dfad..2fdb582 100755
--- a/packages/gl-react-native/src/ExponentTextureLoader.js
+++ b/packages/gl-react-native/src/ExponentTextureLoader.js
@@ -26,7 +26,7 @@ export default class ExponentTextureLoader extends TextureLoader {
let ignored = false;
const asset = Exponent.Asset.fromModule(module);
const promise =
- Exponent.Asset.fromModule(module)
+ asset
.downloadAsync()
.then(o => {
if (ignored) return;
@@ -34,8 +34,8 @@ export default class ExponentTextureLoader extends TextureLoader {
const { width, height } = asset;
const texture = createTexture(gl, [ width, height ]);
console.log("texture...", texture.shape.slice(0))
- texture.setPixels({ raw: asset, width, height });
console.log("raw", asset)
+ texture.setPixels({ raw: asset, width, height });
this.textures.set(module, texture);
this.loads.delete(module);
return texture;
diff --git a/packages/gl-react-native/src/GLViewNative.js b/packages/gl-react-native/src/GLViewNative.js
index 5b27e60..49a8cad 100755
--- a/packages/gl-react-native/src/GLViewNative.js
+++ b/packages/gl-react-native/src/GLViewNative.js
@@ -10,9 +10,60 @@ const propTypes = {
height: PropTypes.number.isRequired,
};
+const tmpPatch = cb => gl => {
+ const {
+ texSubImage2D,
+ bindFramebuffer,
+ bindRenderbuffer,
+ bindTexture,
+ getParameter,
+ } = gl;
+ //gl.enableLogging = true;
+ gl.texSubImage2D = function (...args) {
+ if (args.length === 9 && args[2] === 0 && args[3] === 0) {
+ const [target, level, , , width, height, format, type, pixels] = args;
+ gl.texImage2D(target, level, format, width, height, 0, format, type, pixels);
+ } else {
+ texSubImage2D.apply(gl, args);
+ }
+ };
+ gl.createRenderbuffer = () => null;
+ gl.framebufferRenderbuffer =
+ gl.renderbufferStorage =
+ () => {};
+ let currentFboBinding = null;
+ gl.bindFramebuffer = (target, fbo) => {
+ currentFboBinding = fbo;
+ bindFramebuffer.call(gl, target, fbo);
+ };
+ let currentRenderbufferBinding = null;
+ gl.bindRenderbuffer = (target, renderbuffer) => {
+ currentRenderbufferBinding = renderbuffer;
+ bindRenderbuffer.call(gl, target, renderbuffer);
+ };
+ let currentTextureBinding = null;
+ gl.bindTexture = (target, texture) => {
+ currentTextureBinding = texture;
+ bindTexture.call(gl, target, texture);
+ };
+ gl.getParameter = (pname) => {
+ if (pname === gl.FRAMEBUFFER_BINDING) {
+ return currentFboBinding;
+ }
+ if (pname === gl.RENDERBUFFER_BINDING) {
+ return currentRenderbufferBinding;
+ }
+ if (pname === gl.TEXTURE_BINDING_2D) {
+ return currentTextureBinding;
+ }
+ return getParameter.call(gl, pname);
+ };
+ return cb(gl);
+};
+
export default class GLViewNative extends Component {
props: {
- onContextCreate: (gl: WebGLRenderingContext)=>void,
+ onContextCreate: (gl: WebGLRenderingContext) => void,
style: any,
width: number,
height: number,
@@ -27,7 +78,7 @@ export default class GLViewNative extends Component {
render() {
const { style, onContextCreate, children, ...rest } = this.props;
- return
+ return
-
+
{children}
;
diff --git a/packages/gl-react-native/src/index.js b/packages/gl-react-native/src/index.js
index 0e7c25f..d68de78 100755
--- a/packages/gl-react-native/src/index.js
+++ b/packages/gl-react-native/src/index.js
@@ -1,4 +1,3 @@
-
//@flow
import {View} from "react-native";
import {createSurface, TextureLoaders} from "gl-react";