Hi.
I am importing a .glb file from Blender, which is then presented in Three js. The file consists of a lot of children, and I then want to make some of the children’s material glow when the specific object is hovered. I have managed to set up a system that detects when the mouse hovers it, and then changes the emesiveIntensity of the object. As you can see below:
import * as THREE from "three"
import Experience from "../experience.js";
import GSAP from "gsap"
export default class Room {
constructor() {
this.experience = new Experience()
this.scene = this.experience.scene
this.resoruces = this.experience.recources
this.renderer = this.experience.renderer.renderer
this.room = this.resoruces.items.room
this.actualRoom = this.room.scene
this.mouse = new THREE.Vector2( Infinity, Infinity );
this.setModel()
this.setupEventListeners()
//Setup new arary that contains the children that should be hovered
this.hoverChildren = this.actualRoom.hoverChildren.filter((child) => {
if (child.name === "About_Me_Machine" || child.name === "Contact_Me_Machine" || child.name === "My_Skills_Machine" || child.name === "Projects_Machine" || child.name === "Space_Invaders_Machine" || child.name === "Pac_Man_Contols") {
return child
}
})
}
setModel() {
this.actualRoom.hoverChildren.forEach((child) => {
child.castShadow = true;
if (child instanceof THREE.Group) {
child.hoverChildren.forEach((groupChild) => {
groupChild.castShadow = true
})
}
});
this.scene.add(this.actualRoom)
this.actualRoom.scale.set(0.08, 0.08, 0.08)
}
//Control mouse move and mouse click
setupEventListeners() {
this.renderer.domElement.addEventListener( 'mousemove', (event) => {
event.preventDefault();
this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
});
//this.renderer.domElement.addEventListener( 'click', onMouseClick );
}
raycast() {
this.INTERSECTED = null;
this.raycaster = new THREE.Raycaster();
this.raycaster.setFromCamera( this.mouse, this.experience.camera.perspectiveCamera );
this.intersects = this.raycaster.intersectObjects( this.hoverChildren );
if ( this.intersects.length > 0 ) {
this.intersects.forEach((element) => {
if (element.object.name === "About_Me_Screen") {
//Hovers About Me Machine
this.INTERSECTED = this.actualRoom.hoverChildren[5].hoverChildren[3]
// this.INTERSECTED.material.color.setRGB(10,0,0)
this.INTERSECTED.material.emissiveIntensity = 5 //When the machine is hovered
this.INTERSECTED.material.toneMapped = false
console.log(this.INTERSECTED.material)
}
})
} else {
//Reset to norms
this.INTERSECTED = this.actualRoom.hoverChildren[5].hoverChildren[3]
this.INTERSECTED.material.emissiveIntensity = 1 //When the machine is not hovered
this.INTERSECTED = null;
}
}
resize() {
}
update() {
this.raycast()
}
}
But this does not look perfect, so I tried implementing UnrealBloom, but I can’t make this work. I have seen a lot saying that you should make all objects to black material, but I can’t figure out how to do that with a glb file.
Note: I have an array with all the objects that should glow, and an array with all the objects that should not glow.
You can see my current code here, where I renderer the scene and implement UnrealBloom:
import * as THREE from "three"
import Experience from "./experience.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js"
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
export default class Renderer {
constructor() {
this.experience = new Experience()
this.sizes = this.experience.sizes
this.scene = this.experience.scene
this.canvas = this.experience.canvas
this.camera = this.experience.camera
this.setRenderer()
}
setRenderer() {
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
});
this.renderer.physicallyCorrectLight = true
this.renderer.outputColorSpace = THREE.SRGBColorSpace
this.renderer.toneMapping = THREE.ReinhardToneMapping
this.renderer.toneMappingExposure = 1.5
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
this.renderer.setSize(this.sizes.width, this.sizes.height)
this.renderer.setPixelRatio(this.sizes.pixelRatio)
//Unreal Bloom
this.renderScene = new RenderPass(this.scene, this.camera.perspectiveCamera)
this.composer = new EffectComposer(this.renderer)
this.composer.renderToScreen = false
this.bloomPass = new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 10, 1)
this.composer.addPass( this.renderScene )
this.composer.addPass( this.bloomPass)
this.finalPass = new ShaderPass(
new THREE.ShaderMaterial({
uniforms: {
baseTexture: { value: null },
bloomTexture: { value: this.composer.renderTarget2.texture }
},
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
defines: {}
}), "baseTexture"
)
this.finalPass.needsSwap = true
this.finalComposer = new EffectComposer(this.renderer)
this.finalComposer.addPass( this.renderScene )
this.finalComposer.addPass( this.finalPass )
}
resize() {
this.renderer.setSize(this.sizes.width, this.sizes.height)
this.renderer.setPixelRatio(this.sizes.pixelRatio)
}
update() {
this.renderer.setClearColor(0x000000);
this.composer.render()
this.renderer.setClearColor(0X202020);
this.finalComposer.render()
}
}
How can you achieve selective UnrealBloom on specific object when you are working with a glb file? I have really hit rock bottom, so I hope you can help .
Please let me know if you want more code.