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?