一、THREE.JS是什么?
谈到
three,那就绕不开webgl,那么什么是webgl呢?哈哈,webgl其实是在一套标准,一套在浏览器端支持3D渲染的标准,浏览器端支持了这套标准后,意味着浏览器端可以按照这套标准进行3D渲染。THREE就是在webgl的基础上对其API进行封装形成的3D库,为什么要进行封装呢?直接使用webgl岂不是性能更加的好?这些问题,其实你回看WEB的发展,大致也就有了答案,为什么后端会针对不同的语言去封装许多的框架呢?比如,PHP的laravel、TP等,Java的spring、springMVC等等。前端也是由之前的原生的HTML到支持各大框架的模板引擎,JS也是由原生到基于DOM操作各种类库,比如jQuery,到后来的模块化、工程化的框架,比如如今市场很热的前端三大框架:VUE、Angular、React。想通这些,自然而然就能够理解了为啥会出现针对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>
当你运行这个初始化的程序的时候,你会发现出现一个青绿色的小球,点击它会变成红色的太阳,如下:
这是一个典型的
THREE程序,将在WEB端使用THREE运行3D程序的最基本的构成都包括进去了,下面就会逐个的将程序分解理解下。
- 引入相关的类库:
// 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>
- 编写
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的,上面我们使用的是轨道控制器OrbitControls,THREE第三方控制器还是很多的,根据不同的需求,可以选择合适的控制器。
// 轨道控制器参数:相机,渲染器元素,控制器控制场景变化的原因就是控制
// 相机的投射矩阵不停的变化,然后渲染器不断的进行渲染。
let controls = new t.OrbitControls(camera,renderer.domElement)
现在一个最基本的场景就搭建完毕了,至于上面的射线拾取场景的物体,感兴趣的小伙伴可以搜索下,去了解。
三、写在最后
我也是自学
THREE没太久,文章中可能也会有认知上的错误或者文字错误,或者案例代码错误,希望大家多多包涵,欢迎指正,共同进步。