I'm currently bringing in a glTF model into ThreeJS and utilizing a PlaneGeometry as the ground. My goal is to have the model project shadows onto the plane/ground.
https://i.sstatic.net/JMyZz.png
https://i.sstatic.net/kIIOsm.png
I've attempted to enable
renderer.shadowMap.enabled = true;
on
const renderer = new THREE.WebGLRenderer({ alpha: true });
I also have 2 lights:
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 10, 0);
scene.add( hemiLight );
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(0, 0, 10);
dirLight.castShadow = true;
dirLight.shadow.camera.top = 200;
dirLight.shadow.camera.bottom = -200;
dirLight.shadow.camera.left = - 200;
dirLight.shadow.camera.right = 200;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 500;
scene.add( dirLight );
Final code
body
{
margin: 0px;
padding: 0px;
}
div#container canvas
{
cursor: grab;
}
div#container canvas:active
{
cursor: grabbing;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Importing 3D Model into Three JS</title>
<script type="module" defer>
import * as THREE from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="61ddcab4cdcdafd9d7ccc4dddcc7cbd5dbcb86cdc1c3">[email protected]</a>/build/three.module.js';
import { GLTFLoader } from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="16627e64737356263827242f3826">[email protected]</a>/examples/jsm/loaders/GLTFLoader.js'; // for .glb and .gltf.glb
// import { OBJLoader } from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8cf8e4fee9e9ccbca2bdbeb5a2bc">[email protected]</a>/examples/jsm/loaders/OBJLoader.js'; // for .obj
import { OrbitControls } from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="32465a40575772021c03000b1c02">[email protected]</a>/examples/jsm/controls/OrbitControls.js';
const container = document.querySelector('div#container');
const path_to_model = './ImportModel/Mini-Game Variety Pack/Models/gltf/tree_forest.gltf.glb';
const loader = new GLTFLoader();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 500);
// Add lights
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 10, 0);
scene.add( hemiLight );
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(0, 0, 10);
dirLight.castShadow = true;
dirLight.shadow.camera.top = 200;
dirLight.shadow.camera.bottom = -200;
dirLight.shadow.camera.left = - 200;
dirLight.shadow.camera.right = 200;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 500;
scene.add( dirLight );
// Make renderer
const renderer = new THREE.WebGLRenderer({
alpha: true
});
// Make transparent
renderer.setClearColor(0xffffff, 0);
// Set it to window size
renderer.setSize(window.innerWidth, window.innerHeight);
// Force shadows
renderer.shadowMap.enabled = true;
// Helper (optional)
// const camera_helper = new THREE.CameraHelper(dirLight.shadow.camera);
// scene.add(camera_helper);
// Double quality
const quality = 2;
renderer.setSize(window.innerWidth * quality, window.innerHeight * quality, false);
// Add mouse movement
const controls = new OrbitControls(camera, renderer.domElement);
// Add floor (plane)
const plane_geometry = new THREE.PlaneGeometry(10, 10);
const plane_material = new THREE.MeshPhongMaterial({
color: 0xffff00,
side: THREE.DoubleSide
});
const plane = new THREE.Mesh(
plane_geometry,
plane_material
);
plane.rotation.x = 1.5708;
plane.castShadow = true;
plane.receiveShadow = true;
scene.add(plane);
console.log(plane);
// Import glTF
loader.load(path_to_model, function (gltf)
{
//gltf.scene.position.y = -5;
//gltf.scene.center();
//gltf.scene.scale.set(0.1, 0.1, 0.1);
// Make it cast shadows
gltf.scene.castShadow = true;
gltf.scene.traverse(function(node)
{
if (node.isMesh)
{
node.castShadow = true;
//node.receiveShadow = true;
}
});
console.log(gltf);
console.log('Adding glTF model to scene...');
scene.add(gltf.scene);
console.log('Model added.');
console.log('Moving camera 5z...');
camera.position.z = 5;
console.log('Camera moved.');
}, undefined, function (error)
{
console.error(error);
});
container.appendChild(renderer.domElement);
function animate()
{
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</head>
<body>
<div id="container">
</div>
</body>
</html>
Updated: swapped out MeshBasicMaterial
with MeshPhongMaterial
on the plane following advice from @Justin.