1
votes

I have a GLTF version 1.0 model that I am importing into Three.js using LegacyGLTFLoader.js. When I do so, everything looks good, except that the model does not receive shadows. I am guessing that this is because the imported model's material is THREE.RawShaderMaterial, which does not support receiving shadows (I think). How can I fix this so that my imported model can receive shadows?

Here is sample code:

// 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();

Here are my resources:

Here is a JSFiddle:

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

1

1 Answers

1
votes

One way to fix the problem is to replace the instance of RawShaderMaterial with MeshStandardMaterial. To get the intended effect, you have to apply the existing texture to the new material like so:

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

You also have to compute normal data for the respective geometry so lighting can be computed correctly. If you need no shadows, the unlint MeshBasicMaterial is actually the better choice.

Updated fiddle: https://jsfiddle.net/e67hbj1q/2/