Three.js - baked map texture
Aus Wikizone
Version vom 5. Februar 2022, 20:12 Uhr von 134.3.74.15 (Diskussion)
Links
Blender uv-mapping (mit Three.js workflow
Einführung
Baked maps sind vorgerenderte Texturen. Sie enthalten quasi alle Lichter und Schatten. Sie werden im 3D Programm erstellt und können dann in Blender als Textur geladen werden. Wie man die Textur erstellt findest du unter Blender uv-mapping.
So wird eine Map eingebunden:
Fallstricke:
- Texture wird falsch gemappt flipY
const bakedTexture = textureLoader.load('baked.jpg')
bakedTexture.flipY = false
- ColorSpace falsch Farbe nicht so gut wie im original Render Texture und Renderer muss eingestellt werden (z.b. auf sRGB)
bakedTexture.encoding = THREE.sRGBEncoding //... renderer.outputEncoding = THREE.sRGBEncoding
Komplettes Beispiel
import './style.css'
import * as dat from 'lil-gui'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
/**
* Base
*/
// Debug
const gui = new dat.GUI({
width: 400
})
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/**
* Loaders
*/
// Texture loader
const textureLoader = new THREE.TextureLoader()
// Draco loader
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('draco/')
// GLTF loader
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
/**
* Textures
*/
const bakedTexture = textureLoader.load('baked.jpg')
bakedTexture.flipY = false
bakedTexture.encoding = THREE.sRGBEncoding
/**
* Materials
*/
const bakedMaterial = new THREE.MeshBasicMaterial({ map: bakedTexture,side: THREE.DoubleSide })
const portalLightMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff})
/**
* Portal
*/
gltfLoader.load(
'portal.glb',
(gltf) => {
//this way we cam traverse bigger scenes but as we merged we could do it manually like:
//const bakedMesh = gltf.scene.children.find((child) => child.name === 'baked')
gltf.scene.traverse(
(child) => {
child.material = bakedMaterial
}
)
scene.add(gltf.scene)
// search emmisive materials
const emissions = ["Lamp1", "Lamp2", "LampPortal"];
const lights = gltf.scene.children.filter( child => emissions.includes(child.name) )
lights.forEach( light => light.material = portalLightMaterial )
console.log(lights)
//const portalLightMesh = gltf.scene.children.find((child) => child.name === 'portalLight')// Brunos solution for each light
}
)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
window.addEventListener('resize', () =>
{
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(45, sizes.width / sizes.height, 0.1, 100)
camera.position.x = 4
camera.position.y = 2
camera.position.z = 4
scene.add(camera)
// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.outputEncoding = THREE.sRGBEncoding
/**
* Animate
*/
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()