3JS #01 – Loading GLTF in three.js and mouse interaction
After a few months of rest, I’m finally able to continue my threejs journey. Devoured the first few lessons and delved right into importing a blender file.
For me the most important part of learning threejs is to be able to load blender files and to emulate the materials. Although I was successful in loading the model, I just don’t think the material for a reflective metallic feel is just there yet. Not sure if it’s because of the poor lighting or I need to explore the different material functions in threejs. However, I like what I’ve technically achieved.
Been enjoying learning threejs and a few web tricks along the way is always an added bonus. Having always pondered on how to amalgamate my multidisciplinary knowledge, I feel enliven through these exercises having sketched out a few end results. Hope to get to them.
I also learned a few more tricks in Blender on converting text to mesh and making them feel more soft.
Let’s do the same recap as last time: to load GLTF, giving it a material, and render it we need to:
Lights: To see our loaded files, we first need to set up lights. Ambient Light & Directional Light. The key light would be the directional light as it’ll need to hit the loaded object.
GLTFLoader: We need to import the GLTF Library and load the GLTF through it.
Find the Object: Inside the load() function, the easiest way is to load the scene but we can get specific with the children array or find objects by name.
Assign Material: Still inside the load() function, we can set the material by assigning a new material, here we used MeshStandardMaterial then changed it’s properties.
Don’t forget to Add the model to the threejs scene.
Update GLTF: to update it we call it inside a boolean condition, still unsure why, but this let’s javascript recognize the loaded object.
Hopefully, this can be a good reminder for me, should I try to load a few more files into it.
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
/**
* Cursor // Pure Javascript
*/
const cursor = {
x: 0,
y: 0
};
window.addEventListener("mousemove", (event) => {
cursor.x = event.clientX / sizes.width - 0.5;
cursor.y = -(event.clientY / sizes.height - 0.5);
});
// Canvas
const canvas = document.querySelector("canvas.webgl");
// Sizes
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
// Scene
const scene = new THREE.Scene();
const ambientLight = new THREE.AmbientLight(0x333333, 1);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 10);
directionalLight.position.set(1, 3, 4);
scene.add(directionalLight);
// Loader
let text = null;
const gltfLoader = new GLTFLoader();
gltfLoader.load(
"models/sample-3d.glb",
(gltf) => {
console.log("success");
console.log(gltf);
text = gltf.scene.children[0];
text.position.x = -2;
text.position.z = 1;
text.rotation.z = Math.PI * 0.1;
// Material
text.material = Object.assign(
new THREE.MeshStandardMaterial({
color: 0x9fcae0,
roughness: 0.05,
metalness: 0.95,
emissive: 0x1a1919
}),
{}
);
scene.add(text);
},
(progress) => {
console.log("progress");
console.log(progress);
},
(error) => {
console.log("error");
console.log(error);
}
);
// Camera
let fov = 105;
const camera = new THREE.PerspectiveCamera(
fov,
sizes.width / sizes.height,
0.1,
100
);
camera.position.x = -10;
camera.position.z = 3.5;
scene.add(camera);
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true
});
renderer.setSize(sizes.width, sizes.height);
// Animate
const clock = new THREE.Clock();
const tick = () => {
const elapsedTime = clock.getElapsedTime();
// Update objects
camera.position.x = cursor.x + 1;
camera.position.y = cursor.y;
// Update gltf
if (!!text) {
text.position.y = Math.sin(elapsedTime * 1) * 0.1 - 0.1; // console.log(text.position.y)
}
// Render
renderer.render(scene, camera);
// Call tick again on the next frame
window.requestAnimationFrame(tick);
};
tick();