three.js 入门详解(一)

2021-03-11 07:31

阅读:598

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

上一篇:docker安装phpmyadmin

下一篇:ajax请求


评论


亲,登录后才可以留言!