简介
在上一课中我们了解了.OBJ
文件,.OBJ
文件格式是很久以前使用的。它只有几何体顶点相关数据,所以它加载的内容都是在一个网格里面的。这样使得我们操作模型比较困难,为了方便就出现很多其它格式的3D模型文件。本节我们主要了解.GLTF 格式
。
.gltf
- 用于显示图形的格式。也是各种3D编辑器之间的传输格式。
.gltf格式
本质上是一个JSON文件。它能描述一整个3D场景,比如一个模型使用多少个网格,网格的旋转、位移等信息。
使用
- 与加载
.OBJ
文件一样都需要先创建,基础代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>学习</title>
</head>
<body>
<canvas id="c2d" class="c2d" width="1000" height="500"></canvas>
<script type="module">
import * as THREE from './file/three.js-dev/build/three.module.js'
import { OrbitControls } from './file/three.js-dev/examples/jsm/controls/OrbitControls.js'
const canvas = document.querySelector('#c2d')
// 渲染器
const renderer = new THREE.WebGLRenderer({ canvas })
const fov = 40 // 视野范围
const aspect = 2 // 相机默认值 画布的宽高比
const near = 0.1 // 近平面
const far = 1000 // 远平面
// 透视投影相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
camera.position.set(1, 1, 1)
camera.lookAt(0, 0, 0)
// 控制相机
const controls = new OrbitControls(camera, canvas)
controls.update()
// 场景
const scene = new THREE.Scene()
scene.background = new THREE.Color('black')
{
// 半球光
const skyColor = 0xb1e1ff // 蓝色
const groundColor = 0xffffff // 白色
const intensity = 1
const light = new THREE.HemisphereLight(skyColor, groundColor, intensity)
scene.add(light)
}
{
// 方向光
const color = 0xffffff
const intensity = 1
const light = new THREE.DirectionalLight(color, intensity)
light.position.set(0, 10, 0)
light.target.position.set(-5, 0, 0)
scene.add(light)
scene.add(light.target)
}
// 渲染
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
</script>
</body>
</html>
- 引入
GLTFLoader
解析插件。
import { GLTFLoader } from './file/three.js-dev/examples/jsm/loaders/GLTFLoader.js'
- 通常情况下加载和显示
.GLTF文件
比.OBJ文件
更简单,因为.GLTF文件
中材质和几何体信息都是在一起的。 - 这里加载的
.glb格式
,它是.GLTF格式
的压缩文件。
{
const gltfLoader = new GLTFLoader()
gltfLoader.load('./file/bingdundun.glb', (gltf) => {
const root = gltf.scene
scene.add(root)
})
}
修改模型
- 解析完成后,生成的就是一个场景对象。
console.log('root', root)
- 可以看见最后生成的是一个
Group
组场景对象。 - 使用
.traverse()
操作场景中的所有对象。
// 遍历所有子对象
root.traverse((child) => {
if (child.isMesh) {
// 内部
if (child.name === 'oldtiger001') {
// 金属度
child.material.metalness = 0.5
// 粗糙度
child.material.roughness = 0.8
}
// 半透明外壳
if (child.name === 'oldtiger002') {
// 启用透明
child.material.transparent = true
// 透明度
child.material.opacity = 0.5
// 透明反射效果
child.material.refractionRatio = 1
child.material.metalness = 0.2
child.material.roughness = 0
}
}
})
.isMesh
网格对象的属性,true
表示是网格对象。.name
在创建模型时定义的网格名。
- 操作就这么简单,需要注意的是网格对象不要找错了。
- 当然你还可以做其他操作,比如找到组对象中的
.animations
属性加载动画等。这里的模型没有添加这一类数据,后面我们在进行了解。