I am creating a component in my three js app to create a dirt, rust and scratches overlay according to the health of each model. How to achieve this efficiently and with realism. The method I tried was overlaying some images of rust, dirt and scratches with black background on top of models but I can’t remove the black background and It’s doesn’t look good. Basically I need them to display over the default material without changing it anyhow. Can somebody help? My code till now
import React, { useEffect, useRef, useState } from ‘react’;
import { useThree } from ‘@react-three/fiber’;
import * as THREE from ‘three’;const TextureWearManager = ({ modelRef, mode }) => {
const wearSystemsRef = useRef(new Map());
const [isInitialized, setIsInitialized] = useState(false);
const { scene } = useThree();const loadAndProcessTexture = (url) => { return new Promise((resolve) => { const loader = new THREE.TextureLoader(); loader.load(url, (texture) => { texture.encoding = THREE.sRGBEncoding; texture.flipY = false; texture.repeat.set(0.5, 0.5); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.needsUpdate = true; resolve(texture); }); }); }; const initializeWearSystems = async () => { const [scratchesTexture, rustTexture, dirtTexture] = await Promise.all([ loadAndProcessTexture('/scratches.jpg'), loadAndProcessTexture('/Rust.png'), loadAndProcessTexture('/Dirt.jpg') ]); const processObject = (object) => { if (object.isMesh) { // Create a separate mesh for the overlay const overlayGeometry = object.geometry.clone(); const overlayMaterial = new THREE.MeshBasicMaterial({ transparent: true, opacity: 0.9, map: scratchesTexture, blending: THREE.MultiplyBlending, depthWrite: false }); const overlayMesh = new THREE.Mesh(overlayGeometry, overlayMaterial); overlayMesh.position.copy(object.position); overlayMesh.rotation.copy(object.rotation); overlayMesh.scale.copy(object.scale); overlayMesh.renderOrder = 1; object.parent.add(overlayMesh); wearSystemsRef.current.set(object.name, overlayMesh); } }; if (mode === 'crafting') { scene.traverse(processObject); } else if (modelRef.current) { modelRef.current.traverse(processObject); } setIsInitialized(true); }; const cleanupWearSystems = () => { wearSystemsRef.current.forEach((overlayMesh) => { if (overlayMesh.parent) { overlayMesh.parent.remove(overlayMesh); } if (overlayMesh.geometry) { overlayMesh.geometry.dispose(); } if (overlayMesh.material) { if (overlayMesh.material.map) overlayMesh.material.map.dispose(); overlayMesh.material.dispose(); } }); wearSystemsRef.current.clear(); }; useEffect(() => { if (!isInitialized) { initializeWearSystems(); } return () => cleanupWearSystems(); }, []); return null;
};
export default TextureWearManager;