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

Three.js立方体贴图失败,多环境运行均显示黑屏求助

Three.js 贴图黑屏问题排查与修复

核心问题分析

两段代码均出现黑屏,主要原因集中在本地图片路径错误和浏览器安全限制:

  • 代码中使用了Windows绝对路径C:\\Users\\User\\Desktop\\test.jpg,无论是直接打开HTML文件(file://协议)还是通过Node.js服务器运行,浏览器都无法正确读取该路径下的图片(同源策略限制,服务器环境下路径也不符合Web资源寻址规则)。
  • 未添加纹理加载的错误处理,无法直观排查图片加载失败的问题。
  • ChatGPT生成的立方体初始状态正面正对相机,若纹理加载失败,黑色材质会直接填满视野;Blackbox的平面若纹理加载失败,同样显示黑色。

修复步骤

  1. 调整文件结构:将test.jpg与HTML文件放在同一目录下。
  2. 修改纹理路径:将绝对路径改为相对路径./test.jpg。
  3. 添加加载回调:为TextureLoader.load()添加加载完成、进度、错误回调,便于排查问题。
  4. 优化视觉反馈:给立方体/平面添加初始旋转或调整尺寸,确保即使纹理加载成功也能直观看到效果。

修正后的代码

ChatGPT版本(立方体)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js cube</title>
    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
<div id="canvas-container"></div>

<script>
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('canvas-container').appendChild(renderer.domElement);

    const textureLoader = new THREE.TextureLoader();
    // 使用相对路径,并添加加载回调
    const texture = textureLoader.load(
        './test.jpg',
        () => console.log('纹理加载成功'),
        (progress) => console.log(`加载进度:${(progress.loaded / progress.total * 100).toFixed(2)}%`),
        (err) => console.error('纹理加载失败:', err)
    );

    const material = new THREE.MeshBasicMaterial({ map: texture });
    const geometry = new THREE.BoxGeometry();
    const cube = new THREE.Mesh(geometry, material);
    // 添加初始旋转,便于看到立方体的多个面
    cube.rotation.set(0.2, 0.3, 0);
    scene.add(cube);

    let isDragging = false;
    let previousMousePosition = { x: 0, y: 0 };
    
    function onMouseMove(event) {
        const deltaMove = {
            x: event.offsetX - previousMousePosition.x,
            y: event.offsetY - previousMousePosition.y
        };
        if (isDragging) {
            const deltaRotationQuaternion = new THREE.Quaternion()
                .setFromEuler(new THREE.Euler(
                    toRadians(deltaMove.y * 1),
                    toRadians(deltaMove.x * 1),
                    0,
                    'XYZ'
                ));
            cube.quaternion.multiplyQuaternions(deltaRotationQuaternion, cube.quaternion);
        }
        previousMousePosition = { x: event.offsetX, y: event.offsetY };
    }
    
    function onMouseDown(event) {
        isDragging = true;
        previousMousePosition = { x: event.offsetX, y: event.offsetY };
    }
    
    function onMouseUp() {
        isDragging = false;
    }
    
    document.addEventListener('mousedown', onMouseDown, false);
    document.addEventListener('mouseup', onMouseUp, false);
    document.addEventListener('mousemove', onMouseMove, false);

    function toRadians(degrees) {
        return degrees * (Math.PI / 180);
    }

    function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    }

    animate();
</script>
</body>
</html>

Blackbox版本(平面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Three.js Image Rotation</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    const loader = new THREE.TextureLoader();
    // 使用相对路径,并添加加载回调
    const texture = loader.load(
        './test.jpg',
        () => console.log('纹理加载成功'),
        (progress) => console.log(`加载进度:${(progress.loaded / progress.total * 100).toFixed(2)}%`),
        (err) => console.error('纹理加载失败:', err)
    );

    const geometry = new THREE.PlaneGeometry(3, 3); // 放大平面,便于观察
    const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide });
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    function handleMouseMove(event) {
        const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
        const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
        mesh.rotation.y = Math.atan2(mouseX, mouseY);
    }

    renderer.domElement.addEventListener('mousemove', handleMouseMove, false);

    function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    }

    animate();
</script>
</body>
</html>

额外验证建议

  • 运行服务器时,确保服务器根目录包含HTML文件和图片,访问地址为http://localhost:端口号/test.html。
  • 打开浏览器开发者工具(F12),查看Console面板是否有加载错误提示,Network面板查看图片请求状态。

内容的提问来源于stack exchange,提问作者Jason Vord

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:55:18