mirror of
https://github.com/gre/gl-react.git
synced 2026-01-18 16:16:59 +00:00
continue docs
This commit is contained in:
parent
8271600843
commit
abef910821
@ -13,5 +13,7 @@
|
||||
* [Touch Responsive](/docs/examples/5.md)
|
||||
* [Animation](/docs/examples/6.md)
|
||||
* [Blur (2-Pass)](/docs/examples/7.md)
|
||||
* [Blur+Hue over UI](/docs/examples/8.md)
|
||||
* [Texture from array](/docs/examples/9.md)
|
||||
* [Advanced Effects Examples](/docs/examples/advancedeffects.md)
|
||||
* [Sharing code across gl-react and gl-react-native](/docs/universal.md)
|
||||
|
||||
@ -86,7 +86,7 @@ A texture uniform value can be one of these formats:
|
||||
- an image URL (String).
|
||||
- an Object with an `uri` image URL. This is React Native format (same format as the `source` prop of `React.Image`). `require("image!localImage")` is also supported.
|
||||
- Virtual DOM of any content to be rasterized, see [GL.Uniform][Uniform.md] for more information.
|
||||
- **(only in gl-react)**: a `ndarray` image data value. This allows to gives computed value as a texture.
|
||||
- **(only in gl-react)**: a `ndarray` image data value. This allows to gives computed value as a texture. *For more information on accepted `ndarray` formats, checkout [gl-texture2d documentation](https://github.com/stackgl/gl-texture2d#var-tex--createtexturegl-array)*.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -52,3 +52,23 @@ A GL component is implemented in 2 parts:
|
||||
- first, you need to implement a fragment shader in GLSL (OpenGL Shading Language).
|
||||
Give it to `GL.Shaders.create` and you have a backed object in return (like `StyleSheet.create`).
|
||||
- second, you can render a `<GL.View>` and pass-in the shader you have defined previously. **Do not forget to give a width and height**.
|
||||
|
||||
### Improved version
|
||||
|
||||
Now, we can rewrite this code to make it more "generic" like this:
|
||||
|
||||
```js
|
||||
...
|
||||
|
||||
class HelloGL extends GL.Component {
|
||||
render () {
|
||||
const { ...rest } = this.props;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.helloGL}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That way, we not only allow `width` and `height` to flow in `GL.View` but any other props (we will see later the power of this).
|
||||
|
||||
@ -40,11 +40,10 @@ void main () {
|
||||
|
||||
class Saturation extends GL.Component {
|
||||
render () {
|
||||
const { width, height, factor, image } = this.props;
|
||||
const { factor, image, ...rest } = this.props;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.saturation}
|
||||
width={width}
|
||||
height={height}
|
||||
uniforms={{ factor, image }}
|
||||
/>;
|
||||
}
|
||||
|
||||
@ -66,11 +66,10 @@ void main() {
|
||||
|
||||
class HueRotate extends GL.Component {
|
||||
render () {
|
||||
const { width, height, hue, children } = this.props;
|
||||
const { hue, children, ...rest } = this.props;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.hueRotate}
|
||||
width={width}
|
||||
height={height}
|
||||
uniforms={{ hue }}>
|
||||
<GL.Uniform name="tex">{children}</GL.Uniform>
|
||||
</GL.View>;
|
||||
@ -81,3 +80,23 @@ class HueRotate extends GL.Component {
|
||||
The `GL.Uniform` describes which texture uniform is used for the rasterization of its children content.
|
||||
|
||||
> Note how powerful it is to **compose** React Components that way.
|
||||
|
||||
### Improved version
|
||||
|
||||
Here is an even more concise way of writing your component.
|
||||
|
||||
```js
|
||||
...
|
||||
class HueRotate extends GL.Component {
|
||||
render () {
|
||||
const { hue, children: tex, ...rest } = this.props;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.hueRotate}
|
||||
uniforms={{ hue, tex }}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Remember that you can totally avoid to use `GL.Uniform` and give everything to `uniforms` props.
|
||||
|
||||
@ -46,12 +46,11 @@ class HelloGL extends GL.Component {
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
render () {
|
||||
const { width, height } = this.props;
|
||||
const { ...rest } = this.props;
|
||||
const { value } = this.state;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.helloGL}
|
||||
width={width}
|
||||
height={height}
|
||||
uniforms={{ value }}
|
||||
/>;
|
||||
}
|
||||
|
||||
@ -19,17 +19,18 @@ and stack it into these 2 passes.
|
||||
```js
|
||||
class Blur1D extends GL.Component {
|
||||
render () {
|
||||
const { width, height, direction, children } = this.props;
|
||||
const { width, height, direction, children: t, ...rest } = this.props;
|
||||
return <GL.View
|
||||
{...rest}
|
||||
shader={shaders.blur1D}
|
||||
width={width}
|
||||
height={height}
|
||||
uniforms={{
|
||||
direction,
|
||||
resolution: [ width, height ]
|
||||
}}>
|
||||
<GL.Uniform name="t">{children}</GL.Uniform>
|
||||
</GL.View>;
|
||||
resolution: [ width, height ],
|
||||
t
|
||||
}}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -52,9 +53,9 @@ class Blur extends GL.Component {
|
||||
|
||||
In this simple example, `Blur` has 2 passes: one on X dimension, then one on Y dimension.
|
||||
|
||||
For a more advanced (4-Pass) example, see [Examples/Blur](https://github.com/ProjectSeptemberInc/gl-react/tree/master/Examples/Blur).
|
||||
### 4-pass
|
||||
|
||||
**Extract:**
|
||||
(Used in [Examples/Blur](https://github.com/ProjectSeptemberInc/gl-react/tree/master/Examples/Blur))
|
||||
|
||||
```js
|
||||
class Blur4Pass extends GL.Component {
|
||||
@ -75,3 +76,77 @@ class Blur4Pass extends GL.Component {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### N-pass
|
||||
|
||||
(Used in [Examples/VideoBlur](https://github.com/ProjectSeptemberInc/gl-react/tree/master/Examples/VideoBlur))
|
||||
|
||||
```js
|
||||
const React = require("react");
|
||||
const GL = require("gl-react");
|
||||
const {
|
||||
PropTypes
|
||||
} = React;
|
||||
const Blur1D = require("./Blur1D");
|
||||
|
||||
const NORM = Math.sqrt(2)/2;
|
||||
|
||||
function directionForPass (p, factor, total) {
|
||||
const f = factor * p / total;
|
||||
switch (p%4) {
|
||||
case 0: return [f,0];
|
||||
case 1: return [0,f];
|
||||
case 2: return [f*NORM,f*NORM];
|
||||
case 3: return [f*NORM,-f*NORM];
|
||||
}
|
||||
return p%2 ? [f,0] : [0,f];
|
||||
}
|
||||
|
||||
class Blur extends GL.Component {
|
||||
render () {
|
||||
const { width, height, factor, children, passes, ...rest } = this.props;
|
||||
|
||||
const rec = p => p <= 0 ? children :
|
||||
<Blur1D {...rest} width={width} height={height} direction={directionForPass(p, factor, passes)}>
|
||||
{rec(p-1)}
|
||||
</Blur1D>;
|
||||
|
||||
return rec(passes);
|
||||
}
|
||||
}
|
||||
|
||||
Blur.defaultProps = {
|
||||
passes: 2
|
||||
};
|
||||
|
||||
Blur.propTypes = {
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
factor: PropTypes.number.isRequired,
|
||||
children: PropTypes.any.isRequired,
|
||||
passes: PropTypes.number
|
||||
};
|
||||
|
||||
module.exports = Blur;
|
||||
```
|
||||
|
||||
|
||||
**Usages:**
|
||||
|
||||
- Small blur:
|
||||
|
||||
```html
|
||||
<Blur factor={0.5} passes={2} width={w} height={h}>{any}</Blur>
|
||||
```
|
||||
|
||||
- Medium blur:
|
||||
|
||||
```html
|
||||
<Blur factor={2} passes={4} width={w} height={h}>{any}</Blur>
|
||||
```
|
||||
|
||||
- Powerful blur:
|
||||
|
||||
```html
|
||||
<Blur factor={20} passes={6} width={w} height={h}>{any}</Blur>
|
||||
```
|
||||
|
||||
BIN
docs/examples/8.gif
Normal file
BIN
docs/examples/8.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
40
docs/examples/8.md
Normal file
40
docs/examples/8.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Blur+Hue over UI
|
||||
|
||||
> This example is only available in `gl-react-native`.
|
||||
Implementing it in `gl-react` would be possible if reimplementing the whole UI in a Canvas. However, we can't do it by just using DOM like we can easily use Views in `gl-react-native`.
|
||||
|
||||

|
||||
|
||||
## Implementation
|
||||
|
||||
```html
|
||||
<Blur
|
||||
autoRedraw
|
||||
eventsThrough
|
||||
visibleContent
|
||||
width={256}
|
||||
height={160}
|
||||
factor={factor}>
|
||||
|
||||
<HueRotate hue={-switch1 + 2 * switch2 + 4 * switch3}>
|
||||
|
||||
<View style={{ width: 256, height: 160, padding: 10 }}>
|
||||
<SliderIOS style={{ height: 80 }} maximumValue={2} onValueChange={factor => this.setState({ factor })} />
|
||||
<View style={{ height: 60, flexDirection: "row", alignItems: "center" }}>
|
||||
<SwitchIOS style={{flex:1}} value={switch1} onValueChange={switch1 => this.setState({ switch1 })} />
|
||||
<SwitchIOS style={{flex:1}} value={switch2} onValueChange={switch2 => this.setState({ switch2 })} />
|
||||
<SwitchIOS style={{flex:1}} value={switch3} onValueChange={switch3 => this.setState({ switch3 })} />
|
||||
</View>
|
||||
<ProgressViewIOS progress={factor} style={{height: 10, marginTop: 8, flex:1}} />
|
||||
|
||||
</View>
|
||||
</HueRotate>
|
||||
</Blur>
|
||||
```
|
||||
|
||||
### autoRedraw, eventsThrough and visibleContent
|
||||
|
||||
These 3 props are essential to make this example work:
|
||||
- `autoRedraw` makes the view continously re-render *(and in an efficient way, the render loop is implemented in Objective-C. in `gl-react` context, it is also a bit more performant)*. In our example, we need to do that because we **can't observe UI animation changes** (like when I smoothly move the switch) so we just assume the UI always changes and needs a redraw.
|
||||
- `eventsThrough` allows to make touch events going through the GL view: we don't want our effect layer to respond for those events but the underlying content with the slider and switches.
|
||||
- `visibleContent` prevents the content (our view with the slider and switches) to be hidden. When used with `eventsThrough`, it makes the content intercepting the events.
|
||||
BIN
docs/examples/9.gif
Normal file
BIN
docs/examples/9.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 MiB |
105
docs/examples/9.md
Normal file
105
docs/examples/9.md
Normal file
@ -0,0 +1,105 @@
|
||||
# Texture from array
|
||||
|
||||
> This example is only available in `gl-react`. `ndarray` support is not easy to bring for `gl-react-native` but [feel free to help in this issue](https://github.com/ProjectSeptemberInc/gl-react-native/issues/14).
|
||||
|
||||
```html
|
||||
<Colorify width={256} height={190} colorScale={colorScales[colorScale]} disableLinearInterpolation={disableLinearInterpolation}>
|
||||
http://i.imgur.com/iPKTONG.jpg
|
||||
</Colorify>
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Implementation
|
||||
|
||||
This specific `Colorify` component both display the image and the bottom "gradient bar" that renders the color scale applied.
|
||||
|
||||
```js
|
||||
const React = require("react");
|
||||
const GL = require("gl-react");
|
||||
|
||||
const shaders = GL.Shaders.create({
|
||||
colorify: {
|
||||
frag: `
|
||||
precision highp float;
|
||||
varying vec2 uv;
|
||||
uniform sampler2D image;
|
||||
uniform sampler2D colorScale; // used as a lookup texture
|
||||
uniform float legend;
|
||||
|
||||
float monochrome (vec3 c) {
|
||||
return 0.2125 * c.r + 0.7154 * c.g + 0.0721 * c.b;
|
||||
}
|
||||
|
||||
void main () {
|
||||
vec4 imgC = texture2D(image, uv / vec2(1.0, 1.0 - legend) - vec2(0.0, legend));
|
||||
vec4 scaleC = texture2D(colorScale, vec2(monochrome(imgC.rgb), 0.5));
|
||||
float legendArea = step(uv.y, legend);
|
||||
gl_FragColor = step(uv.y, legend - 0.02) * texture2D(colorScale, uv) +
|
||||
step(legend, uv.y) * vec4(scaleC.rgb, imgC.a * scaleC.a);
|
||||
}
|
||||
`
|
||||
}
|
||||
});
|
||||
|
||||
class Colorify extends React.Component {
|
||||
render () {
|
||||
const { width, height, children: image, colorScale, legend, disableLinearInterpolation } = this.props;
|
||||
return <GL.View
|
||||
shader={shaders.colorify}
|
||||
width={width}
|
||||
height={height}
|
||||
uniforms={{ image, legend }}
|
||||
opaque={false}
|
||||
>
|
||||
<GL.Uniform name="colorScale" disableLinearInterpolation={disableLinearInterpolation}>
|
||||
{colorScale}
|
||||
</GL.Uniform>
|
||||
</GL.View>;
|
||||
}
|
||||
}
|
||||
|
||||
Colorify.defaultProps = {
|
||||
legend: 0.06
|
||||
};
|
||||
```
|
||||
|
||||
The `colorScale` uniform that this component takes is a N x 1 image where `x` position is used as a color scale lookup.
|
||||
|
||||
The `disableLinearInterpolation` option in `GL.Uniform` allows to disable the default linear interpolation that creates a nice smoothing in the lookup of `texture2D`.
|
||||
|
||||
Here is the equivalent way using `uniforms` props:
|
||||
|
||||
```js
|
||||
{ colorScale: { value: colorScale, opts: { disableLinearInterpolation } } }
|
||||
```
|
||||
|
||||
### colorScales
|
||||
|
||||
Here is an extract of the colorScales collection:
|
||||
|
||||
```js
|
||||
const colorScales = {
|
||||
classical: ndarray(new Float64Array([
|
||||
0, 0, 1, // blue
|
||||
0.1, 0.7, 1, // cyan
|
||||
0.4, 1, 0.4, // light green
|
||||
1, 0.6, 0, // orange
|
||||
1, 0, 0 // red
|
||||
]), [5, 1, 3]),
|
||||
|
||||
reversedMonochrome: ndarray(new Float64Array([
|
||||
1, 1, 1,
|
||||
0.1, 0.2, 0.3
|
||||
]), [2, 1, 3]),
|
||||
|
||||
opacityFading: ndarray(new Float64Array([
|
||||
1,
|
||||
0
|
||||
]), [2, 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]),
|
||||
};
|
||||
```
|
||||
|
||||
For more information on accepted `ndarray` formats, checkout [gl-texture2d documentation](https://github.com/stackgl/gl-texture2d#var-tex--createtexturegl-array).
|
||||
Loading…
x
Reference in New Issue
Block a user