pmndrs / react-three-fiber

🇨🇭 A React renderer for Three.js
https://docs.pmnd.rs/react-three-fiber
MIT License
27.64k stars 1.6k forks source link

React Native: THREE.GLTFLoader: Couldn\'t load texture in react native #3254

Open lichmac opened 6 months ago

lichmac commented 6 months ago

Description

I got the error in React Native. Threejs throws the texture errors

2024-05-07 16:45:44.771462+0700 unitygpt[7665:9613623] [javascript] 'THREE.GLTFLoader: Couldn\'t load texture', 'blob:70e21b66-0dce-41b4-a77d-cb228e339bd1?offset=0&size=935696' 2024-05-07 16:45:44.779363+0700 unitygpt[7665:9613623] [javascript] 'THREE.GLTFLoader: Couldn\'t load texture', 'blob:c65a591f-43cf-4f79-837f-86fb175dba64?offset=0&size=222888' 2024-05-07 16:45:44.788510+0700 unitygpt[7665:9613623] [javascript] 'THREE.GLTFLoader: Couldn\'t load texture', 'blob:69d1043a-e99b-4467-8942-570b1b6698f0?offset=0&size=7620'

This is my model

avatar.zip

Reproduction steps

  1. Only follow this one to install https://docs.pmnd.rs/react-three-fiber/getting-started/installation#react-native
  2. Add the other lib "@react-three/drei": "^9.105.6", "@react-three/fiber": "^8.16.3", "expo": "^50.0.0", "expo-gl": "~13.6.0", "react": "18.2.0", "react-native": "0.73.4", "three": "^0.164.1",
  3. Use my below code to load the model
  4. Env information

System: OS: macOS 14.4.1 CPU: (8) arm64 Apple M2 Memory: 496.13 MB / 16.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 18.17.0 path: ~/.nvm/versions/node/v18.17.0/bin/node Yarn: version: 1.22.21 path: ~/.nvm/versions/node/v18.17.0/bin/yarn npm: version: 9.6.7 path: ~/.nvm/versions/node/v18.17.0/bin/npm Watchman: version: 2023.10.30.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.14.2 path: /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms:

Code


import React, { Suspense } from "react";
import { PixelRatio, StyleProp, StyleSheet, View, ViewStyle } from "react-native";
import { Canvas } from "@react-three/fiber/native";
import { useGLTF } from "@react-three/drei/native";

const onCanvasCreated = (state) => {
    // state.camera.lookAt(0, 0, -10);
    const _camera = state.camera, _size = state.size;
    _camera.aspect = _size.width/_size.height;
    _camera.updateProjectionMatrix();
    const _gl = state.gl.getContext();
    _gl.gammaFactor = 2.2;
    const pixelStorei = _gl.pixelStorei.bind(_gl);
    _gl.pixelStorei = function(...args) {
      const [parameter] = args;
      switch (parameter) {
        case _gl.UNPACK_FLIP_Y_WEBGL:
          return pixelStorei(...args);
      }
    };
  };

  function Model(props) {
  const {scene} = useGLTF(modelPath)
  return <primitive
      object={scene}
      rotation={[0, 0, 0]}
      position={[0, -1.5, 0]} />
}

<Canvas
        legacy={true}
        gl={{ antialias: true }}
        dpr={PixelRatio.get()}
        camera={{ fov: 50, near: 0.1, far: 1000, position: [0, 0, 0.8] }}
        onCreated={onCanvasCreated}>
        <ambientLight
          color={0xffffff}
          intensity={0.1} />
        <hemisphereLight
          color={0xffffff}
          intensity={0.5} />
        <directionalLight
          color={0xffffff}
          intensity={1.5}
          position={[0, 1, 5]} />
        <pointLight
          position={[1, 2, -0.5]}
          castShadow={true}
          intensity={2}
          distance={100} />
        <Suspense fallback={null}>
          <Model>
        </Suspense>
      </Canvas>

Screenshots

Screenshot 2024-05-07 at 17 43 36
HoseinKhanBeigi commented 6 months ago

i think The error you're encountering with the GLTFLoader in react-three-fiber is likely due to issues with loading the textures from the GLTF model in a React Native environment.

Ensure that your assets (GLTF model and textures) are correctly bundled and accessible. React Native has different ways to handle static assets compared to a typical web environment.

Use the correct method to load assets in a React Native environment. React Native uses a different way to reference assets using the require function.

import React from 'react';
import { PixelRatio, StyleSheet, View } from 'react-native';
import { Canvas } from '@react-three/fiber/native';
import { OrbitControls } from '@react-three/drei/native';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { useLoader } from '@react-three/fiber';
import { Suspense } from 'react';

const modelPath = require('./assets/model.glb');

const onCanvasCreated = (state) => {
  const _camera = state.camera;
  const _size = state.size;
  _camera.aspect = _size.width / _size.height;
  _camera.updateProjectionMatrix();
  const _gl = state.gl.getContext();
  _gl.gammaFactor = 2.2;
  const pixelStorei = _gl.pixelStorei.bind(_gl);
  _gl.pixelStorei = function (...args) {
    const [parameter] = args;
    switch (parameter) {
      case _gl.UNPACK_FLIP_Y_WEBGL:
        return pixelStorei(...args);
    }
  };
};

function Model(props) {
  const gltf = useLoader(GLTFLoader, modelPath);
  return <primitive object={gltf.scene} {...props} />;
}

export default function App() {
  return (
    <View style={styles.container}>
      <Canvas
        legacy={true}
        gl={{ antialias: true }}
        dpr={PixelRatio.get()}
        camera={{ fov: 50, near: 0.1, far: 1000, position: [0, 0, 0.8] }}
        onCreated={onCanvasCreated}
      >
        <ambientLight color={0xffffff} intensity={0.1} />
        <hemisphereLight color={0xffffff} intensity={0.5} />
        <directionalLight color={0xffffff} intensity={1.5} position={[0, 1, 5]} />
        <pointLight position={[1, 2, -0.5]} castShadow={true} intensity={2} distance={100} />
        <Suspense fallback={null}>
          <Model />
        </Suspense>
        <OrbitControls />
      </Canvas>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});