Three.js LegacyGLTFLoader.js 缺少阴影

Three.js LegacyGLTFLoader.js shadows missing

我有一个 GLTF 1.0 版模型,我正在使用 LegacyGLTFLoader.js 将其导入 Three.js。当我这样做时,一切看起来都很好,只是模型没有接收到阴影。我猜这是因为导入模型的material是THREE.RawShaderMaterial,不支持接收阴影(我认为)。我该如何解决这个问题,以便我导入的模型可以接收阴影?

示例代码如下:

// Construct scene.
var scene = new THREE.Scene();

// Get window dimensions.
var width = window.innerWidth;
var height = window.innerHeight;

// Construct camera.
var camera = new THREE.PerspectiveCamera(75, width/height);
camera.position.set(20, 20, 20);
camera.lookAt(scene.position);

// Construct renderer.
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);

// Construct cube.
var cubeGeometry = new THREE.BoxGeometry(10, 1, 10);
var cubeMaterial = new THREE.MeshPhongMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.translateY(15);
scene.add(cube);

// Construct floor.
var floorGeometry = new THREE.BoxGeometry(20, 1, 20);
var floorMaterial = new THREE.MeshPhongMaterial({color: 0x00ffff});
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
scene.add(floor);

// Construct light.
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 0);
light.castShadow = true;
scene.add(light);

// Construct light helper.
var lightHelper = new THREE.DirectionalLightHelper(light);
scene.add(lightHelper);

// Construct orbit controls.
new THREE.OrbitControls(camera, renderer.domElement);

// Construct GLTF loader.
var loader = new THREE.LegacyGLTFLoader();

// Load GLTF model.
loader.load(
    "https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb",
    function(event) {
        var model = event.scene.children[0];
        var mesh = model.children[0];
        mesh.receiveShadow = true;
        scene.add(model);
    },
    null,
    function(event) {
        alert("Loading model failed."); 
    }
);

// Animates the scene.
var animate = function () {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
};

// Animate the scene.
animate();

这是我的资源:

这是一个 JSFiddle:

https://jsfiddle.net/rmilbert/8tqc3yx4/26/

解决此问题的一种方法是将 RawShaderMaterial 的实例替换为 MeshStandardMaterial。要获得预期效果,您必须将现有纹理应用到新的 material,如下所示:

var newMaterial = new THREE.MeshStandardMaterial( { roughness: 1, metalness: 0 } ); 
newMaterial.map = child.material.uniforms.u_tex.value;

您还必须计算各个几何体的法线数据,以便正确计算光照。如果你不需要阴影,unlint MeshBasicMaterial 实际上是更好的选择。

已更新 fiddle:https://jsfiddle.net/e67hbj1q/2/