THREE.JS00-初识web端的3D流行框架THREE.JS

1,211 阅读5分钟

一、THREE.JS是什么?

谈到three,那就绕不开webgl,那么什么是webgl呢?哈哈,webgl其实是在一套标准,一套在浏览器端支持3D渲染的标准,浏览器端支持了这套标准后,意味着浏览器端可以按照这套标准进行3D渲染。THREE就是在webgl的基础上对其API进行封装形成的3D库,为什么要进行封装呢?直接使用webgl岂不是性能更加的好?这些问题,其实你回看WEB的发展,大致也就有了答案,为什么后端会针对不同的语言去封装许多的框架呢?比如,PHPlaravelTP等,JavaspringspringMVC等等。前端也是由之前的原生的HTML到支持各大框架的模板引擎,JS也是由原生到基于DOM操作各种类库,比如jQuery,到后来的模块化、工程化的框架,比如如今市场很热的前端三大框架:VUEAngularReact。想通这些,自然而然就能够理解了为啥会出现针对WEBGL封装的THREE.js的出现。为了更加方便、更加容易的进行3D开发。

二、简单使用下THREE吧

  • HTML引用CDN的形式使用

THREE的使用和其他的类库的使用的方式基本上相同的, 先引用类库,无论是类库文件下载到本地引用还是通过CDN线上引用方式都是可以的,我们先进行线上引用的方式吧。

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8">
   <title>three自制模板</title>
   <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r99/three.js"></script>
   <!-- 轨道控制器 -->
   <script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
  </head>
  <body>
    <script type="text/javascript">
	const t = THREE
	// console.log(t)
	// 场景
	let scene = new t.Scene()
	// 正交相机
	let w = window.innerWidth
	let h = window.innerHeight
	let k = w / h
	let s = 200 
	let camera = new t.OrthographicCamera(-s*k,s*k,s,-s,1,1000)
	camera.position.set(200,300,400)
	camera.lookAt(scene.position)
	let mouse = new THREE.Vector2()
	let raycaster = new THREE.Raycaster()
	window.addEventListener("click",clickModel,false)
	// 模型拾取函数
	function clickModel(e) {
            console.log(scene)
            mouse.x = (e.clientX / window.innerWidth) * 2 - 1
            mouse.y = - (e.clientY / window.innerHeight) * 2 + 1
            // 更新射线
            raycaster.setFromCamera(mouse,camera)
            // 与射线相交的模型 参数1 检测对象,参数2是否检测该对象
            let intersects = raycaster.intersectObjects(scene.children,true)
            const res = intersects.filter(res => res && res.object)[0];
            if(res && res.object) {
                console.log("选中啦")
                res.object.material.color.set(0xff0000);
             }
	}		
	// 环境光源
	let ambient = new t.AmbientLight(0xfffaaf)
	scene.add(ambient)
	// 点光源
	let point = new t.PointLight(0xffffff)
	point.position.set(400,200,300)
	scene.add(point)
	// 几何体
	let sphere = new t.SphereGeometry(100,60,60)
	// 材质
	let material = new t.MeshLambertMaterial({
            color: 0x00ffac,
            transparent: true,
            opacity: 1
	})
        // 网格模型
	let mesh = new t.Mesh(sphere,material)
	scene.add(mesh)
	// 渲染器
	let renderer = new t.WebGLRenderer()
	renderer.setSize(w,h)
	renderer.setClearColor(0x005566)
	document.body.appendChild(renderer.domElement)
	// 轨道控制器
	let controls = new t.OrbitControls(camera,renderer.domElement)
	// 辅助三维坐标
	let axisHelper = new t.AxisHelper(300)
	scene.add(axisHelper)
	// 渲染函数,根据浏览器的执行帧率来渲染每一帧
	function render() {
            renderer.render(scene,camera)
            requestAnimationFrame(render)
	}
	// 调用渲染函数
	render()
   </script>
  </body>
</html>

当你运行这个初始化的程序的时候,你会发现出现一个青绿色的小球,点击它会变成红色的太阳,如下: 0000.png 这是一个典型的THREE程序,将在WEB端使用THREE运行3D程序的最基本的构成都包括进去了,下面就会逐个的将程序分解理解下。

  1. 引入相关的类库:
// three的核心库
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/r99/three.js"></script>
// three周边提供的 轨道控制器control
<script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
  1. 编写JS逻辑代码:

THREE的一个三维程序最基本的元素是:场景Scene、相机Camera、渲染器Renderer,缺一不可,否则是不能完整的渲染出三维场景的。

  • 场景的初始化:
const t = THREE
// 场景的初始化,场景就可以类比,将真实世界映射出一个虚拟的三维世界
let scene = new t.Scene()
  • 相机的初始化:THREE的相机大致分为两类,一类是正交相机,另一种是透视相机,开发时候常用的是透视相居多。
// 正交相机
let w = window.innerWidth
let h = window.innerHeight
let k = w / h
let s = 200 
// 参数:left right top bottom near far 分别表示视锥体的六个方位投射参数
let camera = new t.OrthographicCamera(-s*k,s*k,s,-s,1,1000)
// position属性是相机的位置属性,可以通过set()方法设置相机的位置数据
camera.position.set(200,300,400)
// lookAt方法是设置相机的指向,参数是一个Vector3()三维点位,
//初始化时通常设置为场景的position
camera.lookAt(scene.position)
  • 渲染器的初始化:渲染器可以理解为将相机的拍摄的场景种的景象实时的惊醒播放
// 初始化渲染器
let renderer = new t.WebGLRenderer()
// 设置渲染器的渲染的范围,通常是three容器的大小
renderer.setSize(w,h)
// 设置 渲染的场景的背景色
// renderer.setClearColor(0x005566)
// 将渲染器的实例放到要渲染的容器中去
document.body.appendChild(renderer.domElement)
  • 按照浏览器帧率刷新
// 渲染函数,根据浏览器的执行帧率来渲染每一帧
function render() {
   renderer.render(scene,camera)
   requestAnimationFrame(render)
}
// 调用渲染函数
render()

按照上面的步骤,其实就已经使用THREE搭建了一个三维场景,但是你如果运行的话会发现,就是一个黑洞洞的场景,什么都没有,是的,因为场景中,没有模型,没有灯光,所以你看到就是黑色的页面。

  • 向场景中添加灯光
// 环境光源:可以理解成自然光,会充满整个空间
let ambient = new t.AmbientLight(0xfffaaf)
scene.add(ambient)  // 添加到场景中去
// 点光源:可以理解为蜡烛等从某一点发出的光
let point = new t.PointLight(0xffffff)
point.position.set(400,200,300)  // 点光源可以设置,光源位置信息
scene.add(point) // 将点光源添加到场景中去

上一步骤中已经向场景中添加了光源,意味着我们看到拍摄的场景不再是漆黑一片,下面我们将向场景中添加模型:

// 几何体 geometry,因为模型向下追去,会发现模型是由点组成的,
// 你可以理解成一个geometry就是存放模型的点集对象,如果模型渲染方式改为 
// new t.Points(sphere,matrrial),就会发现点集了
let sphere = new t.SphereGeometry(100,60,60)
// 材质:你可以理解成模型的外层的覆盖层,决定了模型的各种样式属性,下面是mesh材质
let material = new t.MeshLambertMaterial({
    color: 0x00ffac, // 材质的颜色
    transparent: true, // 材质是否透明
    opacity: 1  // 材质的透明度
})
// 网格模型:模型的渲染方式,本次是利用网格的方式渲染模型
let mesh = new t.Mesh(sphere,material)
scene.add(mesh) // 将模型加载到场景中去

至此,你会发现,场景不再是空空如也了,你找到了刚刚加入的Sphere球体模型,但是,当你鼠标放上去,准备转动模型的时候,你会发现,模型并不会发生变动,这是因为在THREE中想要控制模型放缩和移动,需要借助控制器Control的,上面我们使用的是轨道控制器OrbitControlsTHREE第三方控制器还是很多的,根据不同的需求,可以选择合适的控制器。

// 轨道控制器参数:相机,渲染器元素,控制器控制场景变化的原因就是控制
// 相机的投射矩阵不停的变化,然后渲染器不断的进行渲染。
let controls = new t.OrbitControls(camera,renderer.domElement)

现在一个最基本的场景就搭建完毕了,至于上面的射线拾取场景的物体,感兴趣的小伙伴可以搜索下,去了解。

三、写在最后

我也是自学THREE没太久,文章中可能也会有认知上的错误或者文字错误,或者案例代码错误,希望大家多多包涵,欢迎指正,共同进步。