three.js 入门详解(一)
2021-03-11 07:31
YPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
1. 概述
1.1 什么是WebGL?
WebGL是在浏览器中实现三维效果的一套规范
- 想要使用WebGL原生的API来写3D效果的话,很吃力。three.js是WebGL的一个开源框架,它省去了很多麻烦的细节。
1.2 初识three.js
什么是threejs,很简单,你将它理解成three+js
就可以了。three表示3D的意思
,js表示javascript的意思
。那么合起来,three.js
就是使用javascript
来写3D程序
的意思。
- Javascript是运行在网页端的脚本语言,那么毫无疑问
Three.js
也是运行在浏览器
上的。
1.3 前期准备
1.3.1 下载地址
- three.js 下载地址
1.3.2 目录结构
- Build目录: 包含两个文件,three.js 和three.min.js 。这是three.js最终被引用的文件。一个已经压缩,一个没有压缩的js文件。
- Docs目录: 这里是three.js的帮助文档,里面是各个函数的api,可惜并没有详细的解释。试图用这些文档来学会three.js是不可能的。
- Editor目录: 一个类似3D-max的简单编辑程序,它能创建一些三维物体。
- Examples目录: 一些很有趣的例子demo,可惜没有文档介绍。对图像学理解不深入的同学,学习成本非常高。
- Src目录: 源代码目录,里面是所有源代码。
- Test目录: 一些测试代码,基本没用。
- Utils目录: 存放一些脚本,python文件的工具目录。例如将3D-Max格式的模型转换为three.js特有的json模型。
- .gitignore文件: git工具的过滤规则文件,没有用。
- CONTRIBUTING.md文件: 一个怎么报bug,怎么获得帮助的说明文档。
- LICENSE文件: 版权信息。
- README.md文件: 介绍three.js的一个文件,里面还包含了各个版本的更新内容列表。
1.3.3 配置开发环境
- 浏览器: 推荐使用高版本的浏览器,谷歌、火狐、360等,对于前端开发者来说,chrome是不二的选择
- js 开发工具: VS-code、Webstorm 都可以,为了方便下面的学习,这里使用Webstorm
- Three.js 调试: 利用谷歌浏览器的调试窗口,使用断点调试的方法
2. 开始使用Three.js
使用Three.js之前,首先在部分,需要引入外部文件
Three.js
。
WebGL 的渲染是需要HTML5 中的Canvas
元素的,你可以手动在HTML的部分中使用canvas标签,或者让Three.js帮你生成。这两种选择,一般没有多大差别。我们先手动定义一个canvas标签:
在js里面定义一个函数,将所有执行的代码放在函数里,在html加载完成后,执行该函数
function init{
// 所有需要执行的代码
}
一个典型的Three.js程序,至少应该包括四个部分:渲染器(renderer)
、场景(scene)
、相机(camera)
、以及场景中创建的物体
。
2.1 渲染器(renderer)
渲染器
决定了渲染的结果
应该画在页面的什么元素上面
,并且以怎样的方式来绘制
。渲染器将会和canvas元素进行绑定,如果之前
标签中,定义了
id为canvasId的canvas标签
,那么renderer可以这样写:
var renderer = new THREE.WebGLRenderer({
canvas : document.getElementById(‘canvasId‘);
});
如果想要Three.js生成Canvas元素
的时候,在html中就不需要在定义一个canvas标签了,直接在javascript代码中写道:
var renderer = new THREE.WebGLRenderer();
renderer.setSize = (800,600);
document.body.appendChild(renderer.domElement);
- 上面的代码
setSize
是为canvas元素设置宽高,document.body.appendChild(renderer.domElement)
是将渲染器对应的Canvas元素添加到body
中。
我们可以使用下面的代码(用于清除画面的颜色)将背景色设置为黑色:
renderer.setClearColor(0x000000);
2.2 场景(scene)
在Three.js中添加物体
都是添加到场景
中的,因此它相当于一个大容器。一般说,场景里没有很复杂的操作,只要new一个对象就可以了,然后将物体添加到场景中即可。
var scene = new THREE.Scene();
2.3 照相机(camera)
在介绍照相机之前,我们先来介绍一下坐标系。
- three.js中使用的是右手坐标系,X轴水平向右,y轴垂直向上,Z轴的方向就是屏幕由里往外的方向
这里我们定义一个透视相机
(相机也需要添加到场景中):
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
// 设置相机的位置
camera.position.set(0,0,5);
// 将相机添加到场景中
scene.add(camera);
2.4 创建一个物体
这里我们先介绍一个长方体,创建一个x、y、z方向长度分别为1、2、3的长方体,并设置为红色。
var geometry = new THREE.CubeGeometry(1,2,3);
var material = new THREE.MeshBasicMaterial({
color: 0xff0000;
});
var cube = new THREE.Mesh(geometry,material);
scene.add(cube);
-
new THREE.CubeGeometry(); 表示调用一个几何体
- Cube : 立方体 Geometry : 几何;
-
CubeGeometry
是一个正方体
或者长方体
,究竟是什么,由它的3个参数所决定
CubeGeometry(width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides)
width:立方体x轴的长度
height:立方体y轴的长度
depth:立方体z轴的深度,也就是长度
想一想大家就明白,以上3个参数就能够确定一个立方体。
剩下的几个参数就要费解和复杂一些了,不过后面我们会自己来写一个立方体,到时候,你会更明白这些参数的意义,这里你可以将这些参数省略。
-
new THREE.MeshBasicMaterial(); 表示的是物体的材质
- 你可以在里面设置物体的颜色
var material = new THREE.MeshBasicMaterial({
color: 0xff0000;
});
一定不要忘了,将物体添加到场景
2.5 渲染
在定义了场景中的物体,设置好的照相机之后,渲染器就知道如何渲染出二维的结果了。这时候,我们只需要调用渲染器的渲染函数,就能使其渲染一次了。
renderer.render(scene, camera);
2.6 完整代码
长方体
- 效果图
canvas元素的默认宽高为300/150
3. Three.js功能概览
下面介绍下Three.js官网文档中的一些重要的对象,在你需要寻求帮助时,就能够知道关键词是什么。
-
Cameras(照相机,控制投影方式)
- Camera
- OrthographicCamera
- PerspectiveCamera
-
Core(核心对象)
- BufferGeometry
- Clock(用来记录时间)
- EventDispatcher
- Face3
- Face4
- Geometry
- Object3D
- Projector
- Raycaster(计算鼠标拾取物体时很有用的对象)
-
Lights(光照)
- Light
- AmbientLight
- AreaLight
- DirectionalLight
- HemisphereLight
- PointLight
- SpotLight
-
Loaders(加载器,用来加载特定文件)
- Loader
- BinaryLoader
- GeometryLoader
- ImageLoader
- JSONLoader
- LoadingMonitor
- SceneLoader
- TextureLoader
-
Materials(材质,控制物体的颜色、纹理等)
- Material
- LineBasicMaterial
- LineDashedMaterial
- MeshBasicMaterial
- MeshDepthMaterial
- MeshFaceMaterial
- MeshLambertMaterial
- MeshNormalMaterial
- MeshPhongMaterial
- ParticleBasicMaterial
- ParticleCanvasMaterial
- ParticleDOMMaterial
- ShaderMaterial
- SpriteMaterial
-
Math(和数学相关的对象)
- Box2
- Box3
- Color
- Frustum
- Math
- Matrix3
- Matrix4
- Plane
- Quaternion
- Ray
- Sphere
- Spline
- Triangle
- Vector2
- Vector3
- Vector4
-
Objects(物体)
- Bone
- Line
- LOD
- Mesh(网格,最常用的物体)
- MorphAnimMesh
- Particle
- ParticleSystem
- Ribbon
- SkinnedMesh
- Sprite
-
Renderers(渲染器,可以渲染到不同对象上)
- CanvasRenderer
- WebGLRenderer(使用WebGL渲染,这是本书中最常用的方式)
- WebGLRenderTarget
- WebGLRenderTargetCube
- WebGLShaders(着色器,在最后一章作介绍)
-
Renderers / Renderables
- RenderableFace3
- RenderableFace4
- RenderableLine
- RenderableObject
- RenderableParticle
- RenderableVertex
-
Scenes(场景)
- Fog
- FogExp2
- Scene
-
Textures(纹理)
- CompressedTexture
- DataTexture
- Texture
-
Extras
- FontUtils
- GeometryUtils
- ImageUtils
- SceneUtils
-
Extras / Animation
- Animation
- AnimationHandler
- AnimationMorphTarget
- KeyFrameAnimation
-
Extras / Cameras
- CombinedCamera
- CubeCamera
-
Extras / Core
- Curve
- CurvePath
- Gyroscope
- Path
- Shape
-
Extras / Geometries(几何形状)
- CircleGeometry
- ConvexGeometry
- CubeGeometry
- CylinderGeometry
- ExtrudeGeometry
- IcosahedronGeometry
- LatheGeometry
- OctahedronGeometry
- ParametricGeometry
- PlaneGeometry
- PolyhedronGeometry
- ShapeGeometry
- SphereGeometry
- TetrahedronGeometry
- TextGeometry
- TorusGeometry
- TorusKnotGeometry
- TubeGeometry
-
Extras / Helpers
- ArrowHelper
- AxisHelper
- CameraHelper
- DirectionalLightHelper
- HemisphereLightHelper
- PointLightHelper
- SpotLightHelper
-
Extras / Objects
- ImmediateRenderObject
- LensFlare
- MorphBlendMesh
-
Extras / Renderers / Plugins
- DepthPassPlugin
- LensFlarePlugin
- ShadowMapPlugin
- SpritePlugin
-
Extras / Shaders
- ShaderFlares
- ShaderSprite
我们看到,Three.js功能是十分丰富的,一时间想全部掌握有些困难。在接下来的章节中,我们将会先详细介绍照相机、几何形状、材质、物体等入门级知识;然后介绍使用动画、模型导入、加入光照等功能;最后,对于学有余力的读者,我们将介绍着色器,用于更高级的图形渲染。
4. 照相机
本章将介绍照相机的概念,以及如何使用Three.js设置相应的参数。
4.1 什么是照相机?
在图形学中,照相机可没有生活中的照相机那么简单
- 我们使用的Three.js创建的场景是三维的,而通常情况下显示器是二维的,那么三维的场景怎么在二维的显示器上显示呢?照相机就是一个抽象,它定义了三维空间到二维屏幕投影的方式,用“照相机”这样一个类比,可以使我们直观地理解这一投影方式。
- 而针对
投影方式
的不同,照相机又分为正交投影照相机
与透视投影照相机
。我们需要为自己的程序选择合适的照相机。这两者分别是什么,以及两者有何差异,我们将在下节中作介绍。
4.2 正交投影和透视投影
举个简单的例子来说明正交投影与透视投影照相机的区别。使用透视投影照相
机获得的结果是类似人眼在真实世界中看到的有“近大远小”
的效果(如下图中的(a));而使用正交投影照相机
获得的结果就像我们在数学几何学课上老师教我们画的效果,对于三维空间内平行的线
,投影到二维空间中也一定是平行的
(如下图中的(b))。
一般说来,对于制图、建模软
通常使正交投影
,这样不会因为投影而改变物体比例;而对于其他大多数应用
,通常使用 透视投影
,因为这更接近人眼的观察效果。当然,照相机的选择并没有对错之分,你可以更具应用的特性,选择一个效果更佳的照相机。
4.3 正交投影照相机
4.3.1 参数介绍
正交投影照相机(Orthographic Camera
)
THREE.OrthographicCamera(left, right, top, bottom, near, far)
这六个参数分别代表正交投影照相机拍摄到的空间的六个面的位置,这六个面围成一个长方体,我们称其视景体(Frustum)
。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,而视景体外的物体会在显示之前被裁减掉。
为了保持照相机的横竖比例,需要保证(right - left)与(top - bottom)
的比例与Canvas宽度与高度的比例(800/600)
一致。
// [2-(-2)] / [1.5-(-1.5)] = canvas.width/canvas.height
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10) // left right top bottom near far
near与far
都是指到照相机位置在深度平面的位置,而照相机不应该拍摄到其后方的物体,因此这两个值应该均为正值
。为了保证场景中的物体不会因为太近或太远而被照相机忽略,一般near的值设置得较小
,far的值设置得较大
,具体值视场景中物体的位置等决定。
4.3.2 示例代码
下面我们通过一个具体的例子来了解正交投影照相机的设置
基本设置
- 设置照相机:
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.poaition.set(0,0,5);
scene.add(camera);
- 在原点处创建一个边长为1的正方体,为了和透视效果做对比,这里我们使用
wireframe
而不是实心的材质,以便看到正方体后方的边:
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
})
);
scene.add(cube);
- 效果图:
- 我们看到正交投影的结果是一个正方形,后面的边与前面完全重合了,这也就是正交投影与透视投影的区别所在。
长宽比例
这里,我们的Canvas宽度是800px,高度是600px,照相机水平方向距离4,垂直方向距离3,因此长宽比例保持不变。为了试验长宽比例变化时的效果,我们将照相机水平方向的距离减小为2(right-left = 2):
var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
- 效果图(此时水平方向的距离就被拉长了):
照相机位置
接下来,我们来看看照相机位置对渲染结果的影响。在之前的例子中,我们将照相机设置在(0, 0, 5)位置,而由于照相机默认是面向z轴负方向
放置的,所以能看到在原点处的正方体。现在,如果我们将照相机向右移动1个
单位:
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
// 向右移动一个单位的位置
camera.position.set(1, 0, 5);
- 效果图(物体看上去向左移动了)
- 其实照相机就好比人的眼睛,当我们身体往右移动的时候,看到的物体就好像向左移了。
正交投影摄像机在设置时,是否需要保证left 和 right 互为相反数
呢?
- 下面,我们将原本的参数
(-2, 2, 1.5, -1.5, 1, 10)
改为(-1, 1, 1.5, -1.5, 1, 10)
,即,将视景体设置得更靠右:
var camera = new THREE.OrthographicCamera(-1, 3, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
- 效果图(与之前相机向右的效果是一样的)
换个角度
到目前为止,我们使用照相机,都是沿着Z轴负方向
观察的,因此看到的都是一个正方形,现在我们尝试一下仰望
这个正方体,改变照相机的位置:
// x轴:4; y轴:-3; z轴:5
camera.position.set(4, -3, 5);
照相机默认是沿着z轴的负方向观察的,因此观察不到正方体,只看到一片黑。我们可以通过lookAt函数
指定它看着原点方向
:
camera.lookAt(new THREE.Vector3(0, 0, 0));
- 效果图:
- 注意:
lookAt函数
接收的是一个THREE.Vector3
的实例千万不能写成camera.lookAt(0,0,0)
。
4.4 透视投影照相机
4.4.1 参数介绍
透视投影照相机(Perspective Camera
)
THREE.PerspectiveCamera(fov, aspect, near, far)
让我们通过一张透视照相机投影的图来了解这些参数。
- 透视图中,
灰色
的部分是视景体
,是可能被渲染
的物体所在的区域。fov
是视景体竖直方向上
的张角
(是角度制而非弧度制),如侧视图所示。 -
aspect
等于width / height
,是照相机水平方向和竖直方向长度的比值
,通常设为Canvas的横纵比例
。 -
near和far
分别是照相机到视景体
最近、最远
的距离,均为正值
,且far应大于near
。
4.4.2 示例代码
下面我们通过一个例子来学习透视投影照相机
基本设置
- 设置透视投影照相机,这里Canvas长
800px
,宽600px
,所以aspect
设为800 / 600
:
var camera = new THREE.PerspectiveCamera(45, 800 / 600, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
- 设置一个在原点处的边长为1的正方体:
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
})
);
scene.add(cube);
- 效果图:
- 对比正交透视照相机下正方形的效果,透视投影可以看到
全部的12条边
,而且有近大远小
的效果,这也就是与正交投影的区别。
竖直张角
- 接下来,我们来看下
fov
下一篇:ajax请求