gre / gl-react

gl-react – React library to write and compose WebGL shaders

Home Page:https://gl-react-cookbook.surge.sh

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error with Image on Xiaomi devices

blackcand opened this issue · comments

_bug report

Every time I minimizing the application, I get the error of image always loss. It's just failing with xiaomi devices

with the following code:

// @flow
import * as React from "react";
import { Shaders, Node, GLSL, LinearCopy, Uniform } from "gl-react";

const shaders = Shaders.create({
    contain: {
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float tR;
        uniform vec2 res;
        float r;

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          uv = .5 + .5 * _p * vec2(max(r / tR, 1.), max(tR / r, 1.));
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor =
            step(0.0, uv.x) *
            step(0.0, uv.y) *
            step(uv.x, 1.0) *
            step(uv.y, 1.0) *
            c * sqrt(alpha);
        }
    `,
    },
    free: {
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float zoom;
        uniform vec2 center;
        uniform float tR;
        uniform vec2 res;
        float r;
        
        vec2 invert(vec2 p) {
          return vec2(p.x, 1.0 - p.y);
        }

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          // crop with zoom & center in a cover mode. preserving image ratio
          float maxR = max(r, tR);
          vec2 zoomedCanvasSize = vec2(
            (r / maxR) * zoom,
            (tR / maxR) * zoom
          );
          vec4 crop = vec4(
            center.x - zoomedCanvasSize.x / 2.,
            center.y - zoomedCanvasSize.y / 2.,
            zoomedCanvasSize.x,
            zoomedCanvasSize.y
          );
          // apply the crop rectangle
          uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor =
            step(0.0, uv.x) *
            step(0.0, uv.y) *
            step(uv.x, 1.0) *
            step(uv.y, 1.0) *
            c * sqrt(alpha);
        }
    `,
    },
    cover: {
        // NB the cover vertex code can probably be simplified. good enough for now.
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float zoom;
        uniform vec2 center;
        uniform float tR;
        uniform vec2 res;
        float r;

        vec2 invert(vec2 p) {
          return vec2(p.x, 1.0 - p.y);
        }

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          // crop with zoom & center in a cover mode. preserving image ratio
          float maxR = max(r, tR);
          vec2 zoomedCanvasSize = vec2(
            (r / maxR) * zoom,
            (tR / maxR) * zoom
          );
          vec4 crop = vec4(
            center.x - zoomedCanvasSize.x / 2.,
            center.y - zoomedCanvasSize.y / 2.,
            zoomedCanvasSize.x,
            zoomedCanvasSize.y
          );
          // clamp to not escape the edges
          float w = crop[2], h = crop[3];
          float ratio = w / h;
          if (w > 1.) {
            w = 1.;
            h = w / ratio;
          }
          if (h > 1.) {
            h = 1.;
            w = h * ratio;
          }
          crop = vec4(
            max(0., min(crop.x, 1. - w)),
            max(0., min(crop.y, 1. - h)),
            w,
            h
          );
          // apply the crop rectangle
          uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor = c * sqrt(alpha);
        }
    `,
    },
});

type ImageProps =
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "cover" | "free",
      }
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "contain",
      }
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "stretch",
      };

export default class Image extends React.PureComponent<ImageProps> {
    _isMounted = false;
    static defaultProps = { resizeMode: "cover", center: [0.5, 0.5], zoom: 1, alpha: 1 };

    state = { isAlready: false };

    componentDidMount() {
        this._isMounted = true;
        setTimeout(() => {
            // fix first draw is black screen ~1s
            if (this._isMounted) {
                this.setState({ isAlready: true });
            }
        }, 100);
    }

    componentWillUnmount() {
        this._isMounted = false;
    }

    render(): React.Node {
        let { source, resizeMode, center, zoom, alpha, onDraw, ...rest } = this.props;
        if (!this.state.isAlready) {
            onDraw = undefined;
        }

        if (resizeMode === "cover" || resizeMode === "free") {
            return (
                <Node
                    shader={resizeMode === "cover" ? shaders.cover : shaders.free}
                    uniforms={{
                        t: source,
                        tR: Uniform.textureSizeRatio(source),
                        res: Uniform.Resolution,
                        center,
                        zoom,
                        alpha,
                    }}
                    {...{ onDraw }}
                    {...rest}
                />
            );
        }

        if (resizeMode === "contain") {
            return (
                <Node
                    shader={shaders.contain}
                    uniforms={{
                        t: source,
                        tR: Uniform.textureSizeRatio(source),
                        res: Uniform.Resolution,
                        alpha,
                    }}
                    {...{ onDraw }}
                    {...rest}
                />
            );
        }

        // fallback on stretch, most basic thing
        return <LinearCopy {...rest}>{source}</LinearCopy>;
    }
}

library version

"gl-react": "^3.17.2",
"gl-react-expo": "^3.17.2",
"react-native-view-shot": "^3.1.2",
"react-native": "~0.61.5",

I don't find any solution for this. Any ideas?