一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
学习原因
起因是公司出现新的需求,需要在web端展示3d动画效果,其中会展示环境信息和特定的3D模型以及动画,所以就调研了一下热门的3D技术。在经过对比了一下搜集到的开源工具,包括three.js、Babylon.js、PlayCanvas等,选择three.js的原因是因为它具有非常活跃的社区、大量的使用人群和非常好的学习曲线。
基本概念 官网文档
下面这张图很好的讲述了three.js处于的层次,three.js通过封装webgl实现快速搭建3D页面,减少了学习难度。
编写流程
示例
<html>
<head>
<meta charset="utf-8"> <title>My first three.js app</title>
<style> body { margin: 0; } </style>
</head>
<body>
// https://threejs.org/build/three.js 下载下来
<script src="js/three.js"></script>
<script>
// 场景
const scene = new THREE.Scene();
// 摄像机
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
// render
const renderer = new THREE.WebGLRenderer();
// 网页全铺
renderer.setSize( window.innerWidth, window.innerHeight );
// 将生成的dom添加到body
document.body.appendChild( renderer.domElement );
// 立方体
const geometry = new THREE.BoxGeometry();
// 材质
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// 几何体网格
const cube = new THREE.Mesh( geometry, material );
// 添加到场景
scene.add( cube );
// 摄像机z轴
camera.position.z = 5;
// 帧动画
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
// 运行
animate();
</script>
</body>
</html>
场景: (必须)
创建一个容器空间,可以将你想要进行渲染的元素添加进去,所有需要在此场景中展示出来的物体都需要添加到场景中
1.background属性:
// background可以设置颜色、单个图片、图片组(天空盒)
// 设置图片需要使用new TextureLoader('地址')
// 颜色需要new THREE.Color(0xffffff)
// 背景透明new THREE.WebGLRenderer({antialias: true,alpha:true })
// 天空盒示例:
let r = "http://stemkoski.github.io/Three.js/images/dawnmountain-";
let urls = [
r + "xpos.png",
r + "xneg.png",
r + "ypos.png",
r + "yneg.png",
r + "zpos.png",
r + "zneg.png",
];
let textureCube = new THREE.CubeTextureLoader().load(urls);
scene.background = textureCube;
// fog 属性 线性雾
new THREE.fog(color,near,far)
// 例:new THREE.Fog(0xffffff, 0.015,100)
/ 解释/从最近到最远距离间根据设置的雾气颜色会逐渐变重,最近距离之前不存在雾气,最远距离之后会被雾气遮盖
// FogExp2属性指数雾
FogExp2( color , density )
// 类似Fog,只不过雾气增长速度是指数形式,根据第二个参数来修改,默认是0.00025
相机(必须)
透视相机 PerspectiveCamera(最常用) 物体近大远小
PerspectiveCamera( 视野角度,宽长比,近端点, 远端点 )
正交相机 OrthographicCamera 从各角度看大小相同
const camera = new THREE.OrthographicCamera( 左,右,上,下,近,远);
scene.add( camera );
网格 Mesh
网格需要两个元素组成 几何体 + 材质
几何体
// 平面PlaneGeometry
PlaneGeometry(长,宽)
// 立方体 BoxGeometry 矩形分段数需要在 wireframe线模式 才能看出来
BoxGeometry(长,宽,高,长分段数,宽分段数,高分段数)
// 圆形 CircleGemtry
CircleGeometry(半径, 拆分三角段数, 起始角度, 绘制角数值)
// 圆锥 ConeGeometry
ConeGeometry( 半径, 高度, 拆分三角段数 )
// 圆柱/圆台 CylinderGeometry
CylinderGeometry(顶部半径,底部半径,高度,侧面分段数,高度分段数,起始角度, 绘制角度值)
// 球体 SphereGeometry
SphereGeometry(半径,水平分段数 垂直分段数,-----)
// 边缘几何体EdgesGeometry 绘制出集合体的边缘
// (对比 线模式 可以看到不同点在哪里)
const edges5 = new THREE.EdgesGeometry( geometry5 );
const line = new THREE.LineSegments( edges5, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
形状几何体(ShapeGeometry)根据给出的一些点坐标连城一个线平面
使用canvas绘制线的方法moveTo()、lineTo()、bezierCurveTo()
八面几何体(OctahedronGeometry)、十二面几何体(DodecahedronGeometry)、二十面几何体(IcosahedronGeometry)
圆环几何体(RingGeometry)(二维) 内外为原型的平面、
圆环集合体(TorusGeometry)(三维)、
挤压几何体(ExtrudeGeometry)根据路径生产几何体、车削几何体(LatheGeometry)生产具有轴对称性的网格、等等
材质
基类属性:
name:材质的名字,id:材质的唯一编号
fog:此材质是否受雾影响
visible:材质是否可见,默认值为true
side:平面材质具备,功能是决定渲染哪一面,默认为THREE.FrontSide(正面)。其他选项有THREE.BackSide(反面)和THREE.DoubleSide(两面)。
.shadowSide :定义投影哪一面,值同上
opacity:透明值0-1
map: 贴图 可设置texture
color:颜色0xffffff
specularMap:高光贴图
wireframe :将集合体渲染成线框
envMap :环境贴图,类似天空盒
lightMap:阴影贴图,使用图片渲染为阴影,
MeshBasicMaterial基础网格材质
特点:不受光照影响普通平面
MeshDepthMaterial深度网格材质 depthCube.js
根据物体和摄像头的远近来展示颜色,黑=》白
可以搭配物体融合方法,来模拟物体逐渐远离的场景
MeshDistanceMaterial
内部出现点光阴影效果 暂未搞清具体用途
MeshLambertMaterial
接受光照显示颜色,没有光照会是黑色,根据光照强度改变显示颜色强度
MeshMatcapMaterial 不对灯光作出反应,但是会投射阴影到接受光的物体上
MeshNormalMaterial 法线网格材质 在不同角度看到的颜色不同
MeshPhongMaterial 镜面高光材质 可以模拟具有镜面高光的光泽表面
MeshStandardMaterial 标准网格 对光的反应比MeshPhongMaterial 和MeshLambertMaterial更为精确和逼真,性能要求也会高一些
MeshToonMaterial 一种实现卡通着色的材质。是MeshPhongMaterial材质的一种扩展。受到光照所有面显示
·MeshPhysicalMaterial 物理网格 标准网格的扩展 表现真实模型最为出色
<https://threejs.org/examples/#webgl_materials_physical_clearcoat>
#### 线材质
实线 new THREE.LineBasicMaterial(颜色)
虚线 newTHREE.LineDashedMaterial(颜色)
灯光
环境光AmbientLight
环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。
new THREE.AmbientLight( 0x404040 )
平行光 DirectionalLight
类似太阳发出的光,平行。不产生阴影。
new THREE.DirectionalLight( 0xffffff, 0.5强度 )
点光源PointLight
从一个点向各个方向发射的光源。模拟一个灯泡发出的光。
平面光光源RectAreaLight
从矩形平面均匀发光 模拟窗户
聚光灯(SpotLight)
光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。
半球光(HemisphereLight)
光线照射到除底面以外的其余部分,不能产生阴影
辅助对象
坐标轴辅助
new THREE.AxesHelper(轴线长度);
灯光辅助
PointLightHelper、SpotLightHelper、HemisphereLightHelper
相机视锥体辅助
CameraHelper
加载器
DRACOLoader drc文件加载
DRACO是一个开源库,可以对模型进行压缩,得到的文件比源文件小的多,但是加载时需要额外的解码时间 使用方式 juejin.cn/post/702437…
GLTFLoader glTF格式的文件,three最推荐的模型格式
加载、传输3D格式文件更为高效 blender编辑器导出模型
FontLoader 文字加载器
加载文字 配合 TextGeometry 文字几何体 生成文字
控制器
OrbitControls 常用
轨道控制器 鼠标控制视角 相机围绕目标进行轨道运动
进阶功能
阴影
光源照射在可展示阴影的材质上时,会根据物体形状和照射角度展示出相应的阴影
开启阴影的步骤有
1. renderer.shadowMap.enabled = true;
2.light.castShadow = true;
3.cube.castShadow = true;
plane.reciveShadow = true;
BufferGeometry 基本几何体
所有的几何体都是经过此基础类进行继承封装的;
可以根据自己特定的需求去使用这个类;
废弃对象
所有经过loader加载的物体,具有dispose方法的都需要可以在不使用的时候进行废弃;
矩阵变换 世界坐标 和相对坐标
1A.add(B) B就是A的子元素,B的position是相对于A的position来计算的
移动A的position,B也会跟随A进行移动,可以通过B.getWorldPosition(new THREE.Vectore3())来进行获取B的世界坐标
着色器
需要着色器语言GLSL进行编写,在GPU上运行
ShaderMetrial和RawShaderMaterial 材质编写
解释 shaderMetrial参数文章 blog.csdn.net/weixin_4119…
教学视频 www.bilibili.com/video/BV1kP…
每一集的案例代码codepen.io/collection/…
动画系统
例如glTF模型,加载完成之后存在animations属性,其中包含经过保存的animationClips,我们可以调用这个属性中的动画片段来播放
animation 方法 start stop pause
属性
loop 值 LoopOnce LoopPingPong LoopRepeat pause 暂停/继续