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

uniform sampler2D not working with image URI assets-library and URI base64

hai07t opened this issue · comments

I am trying to render an image from image URI assets-library and URI base64 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 opacity;
      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(opacity);
      }
    `
    },
    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 opacity;
      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(opacity);
      }
    `
    },
    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 opacity;
      void main () {
        vec4 c = texture2D(t, uv);
        gl_FragColor = c / sqrt(opacity);
      }
    `
    }
});

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

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

    render(): React.Node {
        // const { source, resizeMode, center, zoom, opacity, onDraw, ...rest } = this.props;
        const { resizeMode, center, zoom, opacity, onDraw, ...rest } = this.props;
        source = {
            uri:
                "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=="
        };

        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,
                        opacity
                    }}
                    {...{ onDraw }}
                    {...rest}
                />
            );
        }

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

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

I tried to do it like this :

source = {
            uri:
                "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=="
        };

and

  source = {
            uri:
                "assets-library://asset/asset.JPG?id=539425FE-43AA-48E7-9865-D76348208AC7&ext=JPG"
        };

but this does not work. If I use an URL like:

source = { uri: "http://i.imgur.com/rkiglmm.jpg" };

it does work.

I can't find where in the code the images are actually being loaded.

Any ideas?

I use library version

"gl-react": "^3.15.0",
"gl-react-expo": "https://firebasestorage.googleapis.com/v0/b/react-native-ui-kits.appspot.com/o/npm%2Fgl-react-expo-3.16.4.tgz?alt=media&token=57526b5b-96a3-493c-a9d2-288bb5409648",

Thanks!

Hi

I've same issue when use gl react v3. Can someone give the advice?

Thanks

worth trying on gl-react v4
if it still doesn't work, you might want to find a way to either have the pixels ArrayBuffer or to save that image somewhere before using it, see https://docs.expo.io/versions/latest/sdk/gl-view/

The pixels argument of texImage2D() must be null, an ArrayBuffer with pixel data, or an object of the form { localUri } where localUri is the file:// URI of an image in the device's file system. Thus an Asset object could be used once .downloadAsync() has been called on it (and completed) to fetch the resource.

@gre I'm having this issue on v4.0.1

@gre Is there any example on how we can create an ArrayBuffer from a local image?