添加一个Mesh组件

这篇指南会帮你设置你的第一个React Three Fiber的场景

我们会从@react-three/fiber中引入<Canvas />组件,然后把它放到React树中。

import ReactDOM from 'react-dom'
import { Canvas } from '@react-three/fiber'

function App() {
  return (
    <div id="canvas-container">
      <Canvas />
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Canvas组件会在后台做一些非常重要的工作:

— 它设置了一个场景和相机,这是渲染必须的环节

— 它开始每一帧的持续渲染,你不需要自己去定义一个循环渲染

这个教程假设你知道React的基本使用

设置画布

Canvas元素的尺寸会和父元素的尺寸保持同步,所以如果你要设置canvas元素的大小就可以设置父元素的宽和高

你的第一个三维场景

如果你要在场景中看到什么,我们还需要添加一个小写开头的<mesh />元素,这不需要引入,直接就可以用,相当于是去执行new THREE.Mesh()。

<Canvas>
  <mesh />

注意我们不需要去引入任何元素,所有的threejs对象会被自动处理的JSX元素,就像你在React中写<div />写<span />等ReactDOM元素是一样的。基本的一个规则,就是所有在Threejs中的元素在fiber中用小写开头来写(注意Canvas是大写开头的)

Mesh类型是threejs的场景中基本的一种元素,这个元素用来组织几何体(geometry)和材质(material),这样才能组成一个三维的元素。我们可以在创建mesh元素的时候搭配上BoxGeometry几何体和MeshStandardMaterial材质,它们两回自动的绑定到他的父元素mesh对象上。

<Canvas>
  <mesh>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>
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()

让我们暂停一下先来理解下这里到底发生了什么。上面几句代码相当于下面的这些Threejs代码。

结构化参数

在写Threejs代码的时候,如果我们要常见一个BoxGeometry的实例,我们需要在创建的时候传入三个参数:宽、高、深度。

new THREE.BoxGeometry(2, 2, 2)

那么在fiber里面,我们使用args这个参数进行这些数据的设置,这个参数你可以理解为就是我们在用threejs代码创建相应类型实例时要传什么数据,那么就可以通过这里传

<boxGeometry args={[2, 2, 2]} />

注意每次当你去修改了args数据时,对象都会被重构。

添加灯光

接下来,我们要给我们的场景添加一些灯光,只要把组件这样加入到Canvas里面就可以。

<Canvas>
  <ambientLight intensity={0.1} />
  <directionalLight color="red" position={[0, 0, 5]} />

Props 属性

这里呢我们要介绍一下Fiber的基础概念,了解Fiber组件的props是如何和Threejs的元素的属性对应上的。如果你在Fiber组件上设置任何的props,那么其实就是给对应的Threejs的元素设置一样名称的属性。

让我们来看看ambientLight这个组件,从文档上我们能知道构造他的时候可以传入颜色值,同样他也能接受一些props。

<ambientLight intensity={0.1} />
const light = new THREE.AmbientLight()
light.intensity = 0.1

这相当于是

Shortcuts 简化写法

对于一些Threejs中的元素,他们本来有一些set方法,在Fiber组件上呢,有更简化的写法可以达到同样的效果(比如颜色、向量、位置等等)。

const light = new THREE.DirectionalLight()
light.position.set(0, 0, 5)
light.color.set('red')

相当于Fiber组件中下面的写法:

<directionalLight position={[0, 0, 5]} color="red" />

更深入的了解下相关文档。

完整结果

<Canvas>
  <ambientLight intensity={0.1} />
  <directionalLight color="red" position={[0, 0, 5]} />
  <mesh>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>
</Canvas>