You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-three/drei/native远程URL加载纹理失败材质渲染为黑色

问题描述

在React Native应用中尝试使用useTexture加载图像纹理,并将其应用到meshStandardMaterial材质上。当从本地assets文件夹导入图片时,纹理渲染完全正常;但将图片源替换为远程URL时,纹理无法生效,材质渲染为纯黑色。
相关实现代码如下:

import React, { Suspense, useRef } from 'react';
import { View } from 'react-native';
import { Canvas } from '@react-three/fiber/native';
import { useTexture } from '@react-three/drei/native';
import useWindowDimensions from 'react-native/Libraries/Utilities/useWindowDimensions';
import localTexturePath from './assets/duck_texture.png'

function Plane() {
  const ref = useRef();
  // 远程URL加载失效
  const textureUrl = 'https://cdntest.metatube.studio/public/Texture.png'
  // 本地资源加载正常
  // const textureUrl = localTexturePath
  useTexture(textureUrl, (t) => {
    ref.current.map = t
    ref.current.needsUpdate = true
  })
  return(
    <mesh>
      <planeBufferGeometry attach="geometry" args={[3, 3]} />
      <meshStandardMaterial ref={ref} attach="material" color="orange" />
    </mesh>
  )
}

export default function App() {
  const { width, height } = useWindowDimensions();
  return (
    <View
      style={{
        height,
        width,
        backgroundColor: '#FFA000',
      }}
    >
      <Canvas
        onCreated={(s) => {
          s.setSize(width, height);
        }}
        gl={{ physicallyCorrectLights: true }}
        camera={{ position: [-6, 0, 16], fov: 36 }}
      >
        <color attach="background" args={[0xe2f4df]} />
        <ambientLight />
        <directionalLight intensity={1.1} position={[0.5, 0, 0.866]} />
        <directionalLight intensity={0.8} position={[-6, 2, 2]} />
        <Suspense>
          <Plane />
        </Suspense>
      </Canvas>
    </View>
  );
}

已知Three.js本身在Web环境支持通过远程URL加载纹理,需要确认React Native环境下drei的该表现是否为预期行为,以及移动端该如何将远程URL对应的纹理应用到材质上。
项目相关依赖及版本如下:

"@react-three/drei": "^9.11.3",
"@react-three/fiber": "^8.0.21",
"expo": "~45.0.0",
"expo-gl": "~11.3.0",
"react": "18.1.0",
"react-native": "0.69.0-rc.3",
"three": "0.141.0"
问题结论

这个表现是React Native环境下的预期行为,不属于bug。
React Native环境没有浏览器内置的Image元素和网络资源自动加载能力,@react-three/drei/native导出的useTexture默认仅适配了Metro打包的本地静态资源加载逻辑,没有内置远程图片的下载、解码适配,直接传入远程HTTP/HTTPS URL时,底层纹理加载器无法获取到可解析的图像二进制数据,最终会渲染出纯黑默认材质。

解决方案

核心逻辑:不要直接把远程URL传给useTexture,先将远程图片下载到应用本地缓存目录,拿到本地文件路径后再传入加载即可。

  • Expo项目方案(最简便)
    1. 安装expo-asset依赖:expo install expo-asset
    2. 先通过expo-asset下载远程图片到本地缓存,拿到本地URI后再传给useTexture,参考实现:
import React, { Suspense, useRef, useState, useEffect } from 'react';
import { View } from 'react-native';
import { Canvas } from '@react-three/fiber/native';
import { useTexture } from '@react-three/drei/native';
import useWindowDimensions from 'react-native/Libraries/Utilities/useWindowDimensions';
import { Asset } from 'expo-asset';

function Plane() {
  const ref = useRef();
  const [localTexturePath, setLocalTexturePath] = useState(null);

  // 组件挂载时下载远程纹理到本地
  useEffect(() => {
    async function fetchRemoteTexture() {
      const remoteAsset = Asset.fromURI('https://cdntest.metatube.studio/public/Texture.png');
      await remoteAsset.downloadAsync();
      setLocalTexturePath(remoteAsset.localUri);
    }
    fetchRemoteTexture();
  }, []);

  // 本地路径存在后再加载纹理
  const texture = useTexture(localTexturePath, (t) => {
    if (ref.current) {
      ref.current.map = t;
      ref.current.needsUpdate = true;
    }
  });

  if (!localTexturePath) return null;

  return(
    <mesh>
      <planeBufferGeometry attach="geometry" args={[3, 3]} />
      <meshStandardMaterial ref={ref} attach="material" color="orange" />
    </mesh>
  )
}

// 其余App组件代码保持不变即可
  • 裸React Native项目方案
    1. 安装文件读写依赖:npm install react-native-fs --save
    2. 实现逻辑和Expo方案一致:先通过react-native-fs的下载接口把远程图片存到应用缓存目录,拿到file://开头的本地文件路径后,再传给useTexture加载。
注意事项
  • RN环境不存在浏览器端的CORS限制,不需要服务端配置跨域头,但要保证远程图片的HTTPS证书有效,否则iOS/Android原生网络层会直接拦截请求
  • 如果纹理加载后仍然显示异常,可手动配置纹理参数:t.flipY = false、t.colorSpace = THREE.SRGBColorSpace,适配移动端纹理坐标和颜色空间规范
  • 远程纹理加载过程记得搭配Suspense或者加载状态占位,避免纹理未加载完成时组件提前渲染导致报错

内容的提问来源于stack exchange,提问作者Ketan Bhokray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 08:27:24