1.什么是Three.js
Three.js是一款WebGL三维引擎,在所有WebGL引擎中,Three.js是国内资料最多,使用最广泛的三维引擎
2.使用Three.js
在Three.js中1想要渲染物体到网页中,必要的三个对象 场景(scene)、相机(camera)和渲染器(renderer)。
3.创建一个Three.js场景案例
#1.项目中引入Three
#可以使用npm包或直接从git上下载,这里我使用的是git上下载的src中的代码
#REVISION表示当前Three.js的版本
import{REVISION,Scene,PerspectiveCamera,WebGLRenderer} from './src/three.js'
#2.创建场景
var scene = new Scene()
#.创建一个摄像机
var camera = new PerspectiveCamera()
#3.创建一个渲染器
var render = new WebGLRenderer()
#4.添加一个基础材质的立方体到场景中
var geometry = new BoxGeometry()
var material = new MeshBasicMaterial({color:0xff2288})
var cube = new Mesh(geometry,material)
scene.add(cube)
#5.渲染
render.render(scene,camera)
4.Scene对象
Scene场景对象是用来保存画布上所有元素信息的容器,它可以保存对象、光源、物体等信息
4-1.Scene属性
4-1-1.children
返回场景中所有对象的列表,包括摄像机和光源
4-1-2.fog
fog属性可以给场景添加雾化效果,远处的物体会淡淡隐藏,雾化的特点就是场景中的物体离得越远就会越模糊,雾化效果是Three.js的一个方法,调用该方法后,将返回值赋值给scene.fog
scene.fog = new Fog(颜色,最近距离,最远距离)或scene.fog = new FogExp2(雾的颜色,浓度)
4-1-3.overrideMaterial
如果不为空的话,它将使在场景中的一切对象都使用该材料进行渲染,即使物体本身设置了自己的材质,也会被覆盖掉
scene.overrideMaterial = new MeshLambertMaterial({color:0xffffff})
4-2.Scene方法
4-2-1.add()
向场景中添加对象
scene.add(要添加的对象)
4-2-2.remove()
从场景中移除对象
scene.remove(要删除的对象)
4-2-3.traverse()
遍历场景中所有元素执行回调函数
scene.traverse(item =>{console.log(item)})
4-2-4.getObjectByName()
如果在创建元素时给元素添加一个name,就可以在场景对象中使用scene.getObjectByName方法根据name查找元素,第一个参数指定唯一的标识name,第二个参数为true时,在调用者的所有后代上查找
scene.getObjectByName(name,true)
5.perspectiveCamera(透视相机)
这一摄像机使用perspective projection(透视投影)来进行投影,用来模拟人眼所看到的景象,它是3D场景的渲染中使用的最普遍的投影模式,它根据视锥(视锥指的是一个实体形状,看起来像一个被平行地基切除的金字塔,这就是一个透视相机渲染时能看到区域的形状。图片定点对应的发射线和两个裁切平面一起定义了一个截断的金字塔,也就是视锥)的范围给渲染器提供需要渲染的场景范围,实例化new THREE.PerspectiveCamera()接受4个参数来确认视锥的范围,只有在视锥范围内的场景才会渲染,PerspectiveCamera将场景中的物体渲染成近大远小的效果
5-1.参数
5-1-1.fov
摄像机视锥体垂直视野角度
5-1-2.aspect
摄像机视锥体长宽比
5-1-3.near
摄像机视锥体近端面
5-1-4far
摄像机视锥体远端面
5-1-5.zoom
获取或设置摄像机的缩放倍数,默认值为1
5-2.方法
setViewOffset()
设置偏移量,对于多窗口或者多显示器的设置是很有用的
clearViewOffset()
清除任何由setViewOffset()设置的偏移量
getEffectiveFOV()
该方法结合zoom(缩放倍数),以角度返回当前垂直视野角度
updateProjectionMatrix()
更新摄像机投影矩阵,在任何参数修改后·都必须被调用来使改变生效
5-3.位置
对象的基类是object3D(Object3D作为Three中最重要的基础类之一,Camera、Light、Mesh在内的大量类均继承自Object3D,它为需要用到位置、方向等数据的对象提供大量的公共方法及属性)
5-3-1.position
position设置相机在三维坐标中的位置
camera.position.set(0,0,0)或camera.position.x|y|z=0
5-3-2.up
设置相机拍摄时相机头顶的方向
camera.up.set(0,0,0,)或camera.up.x|y|z=0
5-3-3.lookAt
设置相机拍摄时指向的方向
camera.lookAt(0,0,0,)或camera.lookAt.x|y|z=0
6.WebGLRenderer
主要作用就是把相机视锥体的三维场景渲染成一个二维图片显示在画布上
实例化new接受一个对象参数作为渲染器的行为配置,不传参数都会执行其默认值,常用的配置如下:
6-1.
于渲染器绑定的画布节点,不传内部会自己创建一个新的画布节点,使用.domElemnet获取
6-2.
着色器精度,渲染成图片的颜色精度,值://,默认为
6-3.
是否可以设置背景色透明,默认为false
6-4.
是否执行反锯齿,默认为false
6-5.
是否保留绘图缓冲直到手动清除或被覆盖,默认为false
6-6.
最大灯光数,我们的场景中最多能够添加多少个灯光
6-7.
渲染上下文(RenderingContext)对象,就是将渲染器附加到已经创建的WebGL上下文中以方便后期操作,默认为null
6-8.参数
6-8-1.autoClear
定义渲染器是否在渲染每一帧之前自动清除其输出
6-8-2.autoClearColor
定义渲染器是否需要清除颜色缓存,默认是true
6-8-3.autoClearDepth
定义渲染器是否清除深度缓存,默认是true
6-8-4.autoClearStencil
定义渲染器是否需要清除模板缓存,默认为true
6-8-5.domElement
返回画布节点,当配置参数没关联canvas,会自动创建一个新的画布节点,需要手动放入html
6-8-6.shadowMap
是一个对象,当我们需要使用阴影的时候就需要开启它
- 是否允许在场景中使用阴影贴图,默认false
- 是否启动场景中的阴影自动更新,默认是true
- 定义贴图类型,可选值有THREE.BasicShadowMap(性能很好,但质量很差),THREE.PCFShadowMap(默认,性能较差,但边缘更光滑),THREE.PCFSoftShadowMap(性能较差,但边缘更柔软)****THREE.VSMShadowMap(更低的性能,更多的约束,可能会产生意向不到的结果)
6-9.方法
6-9-1.clear
(color:Boolean,depth:Boolean,stwncil:Boolean)渲染器清除颜色、深度或模板缓存
6-9-2.getContext
返回WebGL上下
6-9-3.render
(scene,camera)传入场景和相机,在画布上渲染图片
6-9-4.setClearColor
(color,alpha)设置背景颜色和透明度
6-9-4.setSize
(width,height)修改canvas节点的宽高
7.渲染循环
渲染有两种方式:实时渲染和离线渲染
实时渲染:就是不停的对画面进行渲染,即使画面中没有什么改变,也要重新渲染
例:
function render(){
renderer.render()
requestAnimationFrame(render)
}
7-1.requestAnimationFrame
requestAnimationFrame(回调函数),requestAnimationFrame这个函数就是让浏览器去执行一次参数中的回调函数
8.场景,相机,渲染器之间的关系
three.js中的场景是物体的一个容器
相机的作用就是面对场景,在场景中取一个景,把它拍下来
渲染器的作用就是将相机拍的内容放到浏览器中显示
9.控制器
three.js提供了一些摄像机控件,使用这些控件可以控制场景中的摄像机这些控件放置在Three的发布包中(three/examples/jsm/controls)
9-1.OrbitControls轨道控制器
该控制器可以在特定场景中模拟轨道中的卫星,你可以使用鼠标键盘在场景中游走
通过OrbitControls可以对three的三维场景进行缩放,平移,旋转操作,本质上改变的其实是相机的参数,而不是场景
(camera,domElement)
camera(必须)要控制的相机,该相机不允许是其他对象的子级,除非该对象是场景自身
domElement 用于事件监听的html元素
9-1.参数
- enableRotate 禁止旋转
- enablePan 禁止平移
- enableZoom 禁止缩放
- minDistance 相机距观察目标点的极小距离(模型的最大状态,仅适用于透视摄像机)
- maxDistance 相机距观察目标点的极大距离(模型的最小状态,仅适用于透视摄像机)
- maxZoom 将相机放大多少(仅适用于正交投影摄像机)
- minZoom 将相机缩小多少(仅适用于正交投影摄像机)
- minPolarAngle 垂直旋转的角度下限(范围0到Math.PI,默认值为0)
- maxPolarAngle 垂直旋转的角度上限(范围0到Math.PI,默认值为Math.PI)
- minAzimuthAngle 水平旋转的角度下限
- maxAzimuthAngle 水平旋转的角度上限
- autoRotate true将自动围绕目标旋转(如果启用需要在动画循环里调用update方法)
- autoRotateSpeed 当autoRotate为true时,围绕目标旋转的速度有多快,默认为2.0,相当于在60fps时没旋转一周需要30秒
- enableDamping 将其设置为true以启用阻尼(惯性),这将给控制器带来重量感,默认为false(如果启用需要在动画循环里调用update方法)
- dampingFactor 当enableDamping设置为true,阻尼惯性有多大
- keyPanSpeed 当使用键盘按键的时候,相机平移的速度有多快。默认每次按下按键时平移7像素
- keys 该属性是个对象,包含了用于控制相机平移的按键代码的引用,默认为4个方向箭头键
9-2.FirstPersonControls第一视角控制器
该控制器实现了像第一人称射击游戏一样使用键盘移动角色,使用鼠标控制视角
10.OrthographicCamera(正交投影摄像机)
10-1.参数
- left:左边界,任何比这个左边界远的物体都不会被渲染
- right:右边界,任何比这个右边界远的物体都不会被渲染
- top:上边界
- bottom:下边界
- near:近面距离基于摄像机所在的位置,从这一点开始渲染场景
- far:远面距离,基于摄像机所在的位置,渲染场景到这一点为止
*zoom:变焦这个值设置小于1,场景会被缩小,这个值大于1场景就会放大,设置的值为负数,场景就会上下颠倒
11.封装一个stage对象(ts)
建立一个stage对象,把渲染器、场景、相机、轨道控制器都封装进去,方便重复使用
import { PerspectiveCamera, Scene, WebGLRenderer } from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export default class Stage{
//渲染器
renderer: WebGLRenderer;
//场景
scene:Scene;
//相机
camera:PerspectiveCamera;
//轨道控制器
controls:OrbitControls;
//渲染之前
beforeRender = (time : number = 0)=>{};
//初始化场景
constructor(x : number = 0, y : number = 0, z : number = 12){
this.scene = new Scene();
// antialias:抗锯齿,渲染出来的图像没有小锯齿,但会使渲染效率变低,默认为false
this.renderer = new WebGLRenderer({ antialias: true });
//设置canvas画布的像素尺寸,同时做了自适应尺寸
const { clientWidth, clientHeight } = this.renderer,domElement;
// window.devicePixelRatio是设备物理像素和设备独立像素之间的比率
this.renderer.setSize(clientWidth * window.devicePixelRatio, clientHeight * window.devicePixelRatio, false)
//设置相机视口的宽高比
this.camera = new PerspectiveCamera(45, clientWidth / clientHeight, 0.1, 1000);
//设置相机的位置
this.camera.position.set(x, y, z);
//相机看向的坐标位置
this.camera.lookAt(0, 0, 0);
//设置轨道控制器
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
}
//响应式布局
responsive(){
const { renderer, camera} = this;
if(this.resizeRendererToDisplaySize(renderer)){
const { clientWidth, clientHeight } = renderer.domElement;
camera.aspect = clientWidth / clientHeight;
//更新投影矩阵
camera.updateProjectionMatrix();
}
}
//重置渲染尺寸
resizeRendererToDisplaySize(renderer: WebGLRenderer):boolean{
const {width, height, clientWidth, clientHeight } = renderer.domElement;
const [w, h] = [clientWidth * window.devicePixelRatio, clientHeight * window.devicePixelRatio];
const needResize = width !== w || height !== h;
if(needResize) {
renderer.setSize(w, h, false);
}
return needResize;
}
//连续渲染
animate(time = 0){
this.responsive()
this.beforeRender(time);
this.renderer.render(this.scene, this.camera);
requestAnimationFrame((time) => {
this.animate(time)
})
}
}
网友评论