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

Three.js阴影无法显示问题求助

Three.js 3D模型阴影不显示的修复方案

针对你代码中阴影无法显示的问题,以下是几个关键修复步骤:

1. 配置平行光的阴影相机参数

平行光(DirectionalLight)默认阴影相机的视锥体范围极小,无法覆盖你的模型,导致阴影无法被渲染。需要手动调整参数:

const topLight = new THREE.DirectionalLight(0xffffff, 3); 
topLight.position.set(-1.05307, 2, 4.52525 ); // 适当提高Y轴位置,让阴影向下投射
topLight.castShadow = true;

// 设置阴影相机视锥体范围
topLight.shadow.camera.left = -5;
topLight.shadow.camera.right = 5;
topLight.shadow.camera.top = 5;
topLight.shadow.camera.bottom = -5;
topLight.shadow.camera.near = 0.1;
topLight.shadow.camera.far = 15;
topLight.shadow.camera.updateProjectionMatrix();

// 提高阴影贴图分辨率(可选,让阴影更清晰)
topLight.shadow.mapSize.set(2048, 2048);

scene.add(topLight);

2. 递归设置模型子网格的阴影属性

直接给GLTF场景对象设置castShadow和receiveShadow不会自动应用到所有子网格,必须遍历模型的所有Mesh单独配置:

loader.load(
    `models/${objToRender}/scene.gltf`,
    function (gltf) {
        object = gltf.scene;
        // 遍历所有子网格设置阴影属性
        object.traverse(child => {
            if (child.isMesh) {
                child.castShadow = true;
                child.receiveShadow = true;
            }
        });
        scene.add(object);
        animate(); 
    },
    // 进度、错误回调保持不变
);

3. 添加地面接收阴影

如果场景中没有可接收阴影的物体,模型的阴影会没有投射目标,需要添加一个平面作为地面:

// 在场景初始化后添加地面
const ground = new THREE.Mesh(
    new THREE.PlaneGeometry(10, 10),
    new THREE.MeshStandardMaterial({ color: 0xcccccc })
);
ground.rotation.x = -Math.PI / 2; // 旋转为水平方向
ground.position.y = -1.5; // 调整到恐龙模型下方
ground.receiveShadow = true;
scene.add(ground);

4. 降低环境光强度(可选)

你设置的环境光强度为1,会让阴影变得非常不明显,适当降低可以突出阴影效果:

const ambientLight = new THREE.AmbientLight(0xFFFFFF, objToRender === "dino" ? 0.3 : 1);
scene.add(ambientLight);

修改后的完整代码

import * as THREE from "https://cdn.skypack.dev/three@0.129.0/build/three.module.js";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/loaders/GLTFLoader.js";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
let object;
let controls;
let objToRender = 'dino';

const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; 
document.getElementById("container3D").appendChild(renderer.domElement);

camera.position.z = objToRender === "dino" ? 4 : 500;

// 添加地面接收阴影
const ground = new THREE.Mesh(
    new THREE.PlaneGeometry(10, 10),
    new THREE.MeshStandardMaterial({ color: 0xcccccc })
);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -1.5;
ground.receiveShadow = true;
scene.add(ground);

// 配置平行光及阴影
const topLight = new THREE.DirectionalLight(0xffffff, 3); 
topLight.position.set(-1.05307, 2, 4.52525 );
topLight.castShadow = true;
// 设置阴影相机参数
topLight.shadow.camera.left = -5;
topLight.shadow.camera.right = 5;
topLight.shadow.camera.top = 5;
topLight.shadow.camera.bottom = -5;
topLight.shadow.camera.near = 0.1;
topLight.shadow.camera.far = 15;
topLight.shadow.camera.updateProjectionMatrix();
// 提高阴影贴图分辨率
topLight.shadow.mapSize.set(2048, 2048);
scene.add(topLight);

// 降低环境光强度,让阴影更明显
const ambientLight = new THREE.AmbientLight(0xFFFFFF, objToRender === "dino" ? 0.3 : 1);
scene.add(ambientLight);

const loader = new GLTFLoader();

loader.load(
    `models/${objToRender}/scene.gltf`,
    function (gltf) {
        object = gltf.scene;
        // 遍历子网格设置阴影属性
        object.traverse(child => {
            if (child.isMesh) {
                child.castShadow = true;
                child.receiveShadow = true;
            }
        });
        scene.add(object);
        animate(); 
    },
    function (xhr) {
        const percentage = (xhr.loaded / xhr.total * 100).toFixed(2);
        console.log(percentage + '% loaded');
        document.getElementById("loadingProgress").innerText = `Loading: ${percentage}%`;
    },
    function (error) {
        console.error(error);
    }
);

if (objToRender === "dino") {
    controls = new OrbitControls(camera, renderer.domElement);
}

function animate() {
    requestAnimationFrame(animate);
    if (object && objToRender === "eye") {
        object.rotation.y = -3 + mouseX / window.innerWidth * 3;
        object.rotation.x = -1.2 + mouseY * 2.5 / window.innerHeight;
    }
    renderer.render(scene, camera);
}

window.addEventListener("resize", function () {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

document.onmousemove = (e) => {
    mouseX = e.clientX;
    mouseY = e.clientY;
};

内容的提问来源于stack exchange,提问作者Aleksandar Despotovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:48:15