rnc-archive / react-native-webgl

DEPRECATED: use expo-gl – Implements WebGL for react-native
295 stars 73 forks source link

iOS : Textures not loading on first render (ThreeJS) #16

Closed Kernael closed 4 years ago

Kernael commented 7 years ago

On iOS only, I noticed that my textured meshes do not show on the first render of my WebGL component, but show correctly on every subsequent render.

Component code :

  onContextCreate = (gl) => {
    this.width = 4;
    this.height = (metrics.height / metrics.width) * this.width;
    this.camera = createCamera(this.width, this.height);
    this.gl = gl;
    this.renderer = createRenderer({ gl });
    this.renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
    const context = gl.getExtension('RN');

    this.createScene();

    const animate = () => {
      requestAnimationFrame(animate);

      this.renderer.render(this.scene, this.camera);

      context.endFrame();
    };

    animate();
  };

  createScene = () => {
    this.scene = new THREE.Scene();

    this.background = meshes.createBackground((2000 / metrics.width) * this.width, this.height, this.gl, this.renderer);
    this.plane = meshes.createPlane(this.gl, this.renderer);

    this.scene.add(this.background);
    this.scene.add(this.plane);
  };

  panResponder = PanResponder.create({
    onStartShouldSetPanResponder: () => true,
    onPanResponderGrant: this.touch,
  });

  render() {
    return (
      <WebGLView
        {...this.panResponder.panHandlers}
        style={{ width: metrics.width, height: metrics.height }}
        onContextCreate={this.onContextCreate}
      />
    );
  }

Meshes code :

export const loadThreeJSTexture = (gl, src, texture, renderer) => {
  var properties = renderer.properties.get(texture);
  gl
    .getExtension('RN')
    .loadTexture({ yflip: true, image: src })
    .then(({ texture }) => {
      properties.__webglTexture = texture;
      properties.__webglInit = true;
      texture.needsUpdate = true;
    });
};

export const loadTexture = (gl, src, renderer) => {
  const texture = new THREE.Texture();
  const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true, overdraw: 0.5 });
  loadThreeJSTexture(gl, src, texture, renderer);
  return material;
};

export const createBackground = (width, height, gl, renderer) => {
  const blueBackground = new THREE.BoxGeometry(width, height, 0);
  const material = loadTexture(gl, require('background.png'), renderer);
  const mesh = new THREE.Mesh(blueBackground, material);

  mesh.position.z = -40;

  return mesh;
};

export const createPlane = (gl, renderer) => {
  const geometry = new THREE.PlaneBufferGeometry(0.6, 1);
  const material = loadTexture(gl, require('plane.png'), renderer);
  const mesh = new THREE.Mesh(geometry, material);

  return mesh;
};

export const createStar = (width, x, y) => {
  const geometry = new THREE.CircleGeometry(width, 12);
  const material = new THREE.MeshBasicMaterial({color: 0xff0000});
  const mesh = new THREE.Mesh(geometry, material);

  mesh.position.x = x;
  mesh.position.y = y;
  mesh.position.z = -1;

  return mesh;
};

On the first render only, nothing appears but the red circle star. Am I loading the textures incorrectly ?

gre commented 7 years ago

yes I think there is a bug in current iOS implementation of the image source support. it seems to be a bit random. I need to investigate more, I was able to reproduce it in gl-react too https://github.com/gre/gl-react/issues/153

gre commented 7 years ago

@Kernael would you mind testing if this commit effectively fixes the problem? (my gl-react cookbook issue appears fixed at least)

gre commented 7 years ago

github seems to have missed to mention the commit in this issue but it's in https://github.com/react-community/react-native-webgl/commit/ce6a2b978be38f2df70886d74b838e08b6074dde

Kernael commented 7 years ago

@gre I will be able to test on iOS tomorrow only, but for now I'm not noticing any black textures on Android anymore so it looks good 👍

Just FYI, I had to manually run yarn inside node_modules/react-native-webgl to complete the installation, without this step RN doesn't find react-native-webgl package.

gre commented 7 years ago

my fix does not touch Android at all because I think the bug was just on iOS.

yeah this is because the lib/ folder is not committed. and i'm not sure if latest NPM launches "prepublish" script anymore on custom install (e.g. with a github repo).

gre commented 7 years ago

it's in 0.6.0

Kernael commented 7 years ago

@gre I can now test on iOS and I'm still experiencing the bug with 0.6.0. I could fix it by setting yflip to false though, my textures are all upside down, but they are loading every time. Maybe this can help you ?

gre commented 7 years ago

interesting. could you try to go edit this file in XCode (in RNWebGL project, RNWebGLTextureWithGPUImage.m file )

in the else {

begin with a [source useNextFrameForImageCapture];

maybe this needs to be called on the source, not the filter. if it works, can you try to see if it still works if you remove [filter useNextFrameForImageCapture];

?

Kernael commented 7 years ago

Adding [source useNextFrameForImageCapture]; did not fix the bug, but I have found that the line [filter useNextFrameForImageCapture]; seems to prevent the texture from loading even after the first render.

Kernael commented 6 years ago

Not sure if we should open a new issue or rename this one, but as I mentioned earlier, black textures can happen randomly sometime on Android, even with yflip: false, which seems to fix textures issues on iOS (did not notice any problem since).

gre commented 6 years ago

so basically you are saying that

iOS Android
yflip true bug bug
yflip false fine bug

?

Kernael commented 6 years ago

Thats what I have experienced so far yep. But the issue on Android seems different the one we had on iOS, where all the textures did not load on first render, then fine on other renders. On Android it happens randomly on one or several textures only each time.

gre commented 6 years ago

i've created a new example to try investigate these and on iOS trying to render 9 textures renders just white 🤔 while on Android you have weird inconstencies like mismatch of the image

on first load

screen shot 2017-10-02 at 14 31 06

on reload

screen shot 2017-10-02 at 14 31 33

this if freaking weird. still investigating

gre commented 6 years ago

ok I think I know what's happening. some promise gets resolved too soon.. going to try to fix that now

gre commented 6 years ago

mmh that does not seem the problem (even tho it was probably one thing to fix)

AlexDM0 commented 6 years ago

is there any progress on this?