场景Scene
import * as Three from 'three'
const scene = new Three.Scene()
容纳了一切3d资源 包括物体、光源、摄像机等
网格Mesh
三点确定一个平面 常用若干拼接起来的三角形描述物体的表面 这就是网格
一个网格就是three.js里的一个3d物体
mesh具有位置、旋转、缩放等功能 但它只是一个基础框架
真正渲染的物体还需要几何体Geometry和材质Material的支持
const geometry = new THREE.BoxGeometry(1,1,1)
const material = new THREE.MeshBasicMaterial({color:'red'})
const mesh = new THREE.Mesh(geometry, material)
几何体Geometry
geometry决定了mesh的形状(平面) 也包括法线以参与光照信息
three.js中预设了立方体 三角形 圆锥等形状 参考文档
const geometry = new THREE.BoxGeometry(1,1,1)
这就新建了一个立方体geometry
还可以使用BufferGeometry自定义几何体
材质Material
material决定了mesh看起来怎么样 与光的阴影和反射有关系
three.js中预设了许多材质 参考文档
const material = new THREE.MeshBasicMaterial({color:'red'})
创建一个基础的材质 不参与光照计算
纹理Texture
纹理可以让材质拥有图像的外观
const texture = new THREE.TextureLoader().load('/textures/wood.jpg');
const material = new THREE.MeshStandardMaterial({
map: texture
});
加载第三方资源
使用three.js内置的Loader可以加载3d资源 参考文档
导入.glb或其他3d模型文件可以获取一个mesh的全部信息
.glb / .gltf文件使用GLTFLoader即可
光源
让物体有阴影和反光 只有材质受光照影响的时候才需要
摄像机
分为透视摄像机和正交投影摄像机
参考视频更清晰
透视摄像机
近大远小 类似人眼
正交投影摄像机
按某个方向垂直投影 类似三视图
react-three-fiber
这个库允许我们在react中便捷地配置three.js
// react-three-fiber
<Canvas>
<mesh>
<boxGeometry />
<meshStandardMaterial />
</mesh>
</Canvas>
// three.js
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(width, height)
document.querySelector('#canvas-container').appendChild(renderer.domElement)
const mesh = new THREE.Mesh()
mesh.geometry = new THREE.BoxGeometry()
mesh.material = new THREE.MeshStandardMaterial()
scene.add(mesh)
function animate() {
requestAnimationFrame(animate)
renderer.render(scene, camera)
}
animate()
这两种写法是完全等价的 react-three-fiber只是允许我们用jsx的方式配置动画 并会根据props自动更新、组件销毁时自动释放资源
layers
three.js具有图层的概念
一个图层使用0-31的数字标识 一个对象可以被分配至一个或多个图层
可以为摄像机设置图层 它会只拍摄该图层的内容
@react-three/fiber中 一般只支持用单个数字设置图层 多图层需要直接使用three中的Layers对象
世界坐标
mesh、光源等3D对象嵌套时 其position时相对其父元素的坐标
获取其世界坐标
const meshRef = useRef<Mesh>(null)
<mesh castShadow ref={meshRef}>
<boxGeometry></boxGeometry>
<meshPhysicalMaterial color={'red'} />
</mesh>
// 世界坐标
const worldPosition = meshRef.current.getWorldPosition(new Vector3())
getWorldPosition来自Object3D类型(即任何一个3d对象都有此函数)
getWorldPosition会将结果写在参数1 并将其作为返回值 这是为了变量的复用 避免频繁创建和销毁
还有两个函数可以进行坐标转换: localToWorld worldToLocal
localToWorld将一个相对当前对象的坐标转化为世界坐标 也会把结果写入参数1中并返回
如果不想修改原对象 需要创建其复制作为参数
const someVector = new Vector3(1, 1, 1)
meshRef.current.worldToLocal(someVector.clone())
worldToLocal类似
测试和学习
fanethedivine.github.io/test-three/… 提供了多个参数的调整和实时反馈