目录
前言
在three中,场景、相机、渲染器是最核心的三个概念。我们通过相机拍摄场景,再通过渲染器把场景呈现在视图中。
一、Scene 场景
场景:放置物体、灯光和摄像机的地方。
我们把场景理解为我们现实生活中的空间,在三维世界中我们创建了一个空间,这个空间中什么也没有。我们需要放置物体来点缀我们的空间,也需要光源来照亮我们的空间。
二、Camera 相机
相机是用来拍摄我们想展示的三维空间的内容,在图形学中常用相机分两类:透视相机和正交相机。
-
透视相机是有近大远小的效果,更符合我们人眼的感官视觉效果。
-
正交相机则没有近大远小的效果,一般用于制图类软件中,如CAD软件。
三、WebGLRenderer 渲染器
渲染器则是决定使用什么方式渲染出想要的视图效果,他的入参就是相机和场景,渲染结果从本质上来讲就是一个canvas对象。渲染对象中包含设置canvas画布大小,canvas背景色等多种方法。
四、光源
1. 环境光
环境光是没有方向的光源,立方体的六个面都会受到光线的影响。如果我们只设置环境光,没有设置平行光,那么我们会发现物体还是没有棱角,这是因为物体的六个面都是一样的亮度。
2. 平行光
平行光可以想象为太阳光,太阳光从远处射向地球,因为太阳距离地球太远了,所以太阳光抵达地球时光线的夹角可以忽略不计,光线之间是平行的。当我们设置了平行光后,物体就有了棱角,这是因为物体经过太阳光的照射后产生了反射光,物体不同的面经过不同的入射角后反射的光线也不一致,就有了明暗的区别。
五、threeJS实现3D场景
1. 准备
// 安装项目
yarn create vite three-learn --template react
// 进入目录
cd three-learn
// 安装依赖
yarn
// 安装three,版本为0.136
yarn add three@0.136
// 运行项目
yarn dev
2. 第一个3D场景
我们先绘制出第一个3D场景,让大家更好的理解场景、相机和渲染器的工作流程。
import * as THREE from 'three';
import { useEffect } from 'react'
import './App.css'
const App=()=> {
useEffect(() => {
/** 创建场景 */
const scene = new THREE.Scene();
/** 相机设置 */
const width = window.innerWidth; //窗口宽度
const height = window.innerHeight; //窗口高度
const k = width / height; //窗口宽高比
const s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(400, 200, 300); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/** 创建渲染器对象 */
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0x888888, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
renderer.render(scene, camera); //执行渲染操作
}, [])
return (
<div className="App"></div>
)
}
export default App
这样我们就创建了第一个3D场景,但是访问页面时我们会发现页面上漆黑一片,什么也没显示。这时我们就需要运用到场景了。
3. 第二个3D场景
import * as THREE from 'three';
/** 创建场景 */
const scene = new THREE.Scene();
// 创建一个立方缓冲几何体
const geometry = new THREE.BoxGeometry( 100, 100, 100 )
// 创建材质
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
// 生成带有材质的物体
const cube = new THREE.Mesh( geometry, material );
// 把物体添加进场景中
scene.add( cube );
/** 相机设置 */
const width = window.innerWidth; //窗口宽度
const height = window.innerHeight; //窗口高度
const k = width / height; //窗口宽高比
const s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(400, 200, 300); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/** 创建渲染器对象 */
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0x888888, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
renderer.render(scene, camera); //执行渲染操作
-
和第一个3D场景对比,我们添加了一个物体在场景中,这时就可以在视图中看到一个立方体,但是你会发现该立方体没有立体感,这是因为我们没有设置光源的原因。
-
物体(mesh)是three中最重要的一个部分,就好比我们摄影,物体才是我们最终想拍摄并展现的,光源,相机的摆放等一切都是为了拍摄物体做的准备。当然,这些也决定了我们拍摄出来的效果是否满意。
-
在three中,mesh由几何图形(BufferGeometry)和材质(material)组成,其中几何图形决定物体的形状,材质决定物体的外观。three内置了几种几何形状的类和常用的材质类,也可以自定义扩展,我们后续会细说。
-
这时就可以看出物体拥有了立体感。
-
我们在该段代码中添加了两种光源,环境光(AmbientLight)和平行光(DirectionalLight)
4. 第三个3D场景
import * as THREE from 'three';
/** 创建场景 */
const scene = new THREE.Scene();
// 创建一个立方缓冲几何体
const geometry = new THREE.BoxGeometry( 100, 100, 100 )
// 创建材质
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
// 生成带有材质的物体
const cube = new THREE.Mesh( geometry, material );
// 把物体添加进场景中
scene.add( cube );
// 创建光源
// 环境光,没有特定的方向
const ambientLight = new THREE.AmbientLight(0x444444)
scene.add(ambientLight)
// 平行光,类似于生活中的太阳光
const directionalLight = new THREE.DirectionalLight(0x00ff00, 1)
directionalLight.position.set(400, 200, 300)
scene.add(directionalLight)
/** 相机设置 */
const width = window.innerWidth; //窗口宽度
const height = window.innerHeight; //窗口高度
const k = width / height; //窗口宽高比
const s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(400, 200, 300); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/** 创建渲染器对象 */
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0x888888, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
renderer.render(scene, camera); //执行渲染操作
和第二个3D场景相比,我们添加了光源。但是似乎和没有添加光源并没有区别,这里需要提到下材质(material)。我们在代码中使用的是MeshBasicMaterial材质,这种材质不受光照的影响。我们可以把该材质换成MeshLambertMaterial材质。(8行修改材质)
总结
本文主要记录了threeJS中场景、相机、渲染器、光源的基本概念,以及实现了一个简单的3D场景。下次再见