当前位置:天才代写 > tutorial > 网页教程 > Three.js 入门指南 使用手册基础教程第一章

Three.js 入门指南 使用手册基础教程第一章

2018-08-09 08:00 星期四 所属: 网页教程 浏览:2176

 

Three.js 入门指南

 

 前言

本书介绍了,Three.js相关知识,是一个比较基础,作者非出版!

此JavaScript框架作为前端开发,为计算机科学做出贡献。

欢迎读者给本书提出宝贵意见,也欢迎交流网页前端设计的其他话题。

 



献给所有将创造令人心动的应用的程序员

 

Intel 公司实习阶段,我制作了一个基于 Web Audio 的库 jWebAudio,为了演示这个库的

 

三维音效效果,我决定自学 Three.js。由于之前有计算机图形学等课程的基础,而且

Three.js 中的很多概念是十分容易理解的,最终我在三天内快速地完成了三维打砖块游戏Arcalands。用 Three.js 创建三维图形应用的高效性让我有些吃惊。后来,我又在多个项目中使用了 Three.js,慢慢加深了对它的了解。

回顾学习 Three.js 的过程,我发现虽然目前网上使用 Three.js 的实例很多,但真正系统介绍该库的教程很少,官方文档又不齐全。对于入门者而言,仅仅看着别人的例子和 API 有时候还不足以入门。而我自己是通过很多个项目的实践,才慢慢对 Three.js 有了比较全面的了解。因此,我希望通过这本书给想学习 Three.js 的读者提供一个比较系统的入门介

绍。


本书特色

本书是目前市场上唯一一本介绍 Three.js 技术的书,旨在通过系统化的介绍,让初学者能够着手使用 Three.js,在网页上创建炫酷的三维图形应用,并学会持续学习进阶知识方法。

本书每个章节都通过具体的例子阐释相关知识点,所有代码都可以在 Github 上找到。

 

本书读者

我们常说,这是一个信息爆炸的时代。这就意味着,虽然信息的获取变得越来越廉价,但学习新技术的成本却在不断增加。就作者个人而言,每次在学习一个新技术之前都要斟酌再三,因为可学习的内容越来越多,学习的机会成本也就变大了。所以,在阅读本书前, 请你回答以下问题,如果您有一个回答,那么本书就是为您打造的:

 

· 我学过 JavaScript,想要快速开发一款三维网页游戏,但我没有什么网页游戏开发经验。

· 我想要使用 WebGL,但是我没学过 OpenGL,对图形渲染也没什么概念。

· 我听说过 Three.js,正好想要学学,苦于没有一个完整的教程。

· 我对 Three.js 比较熟悉,想要更全面地了解它,并学习一些高阶的知识。

· 我是来打酱油的,说不定会看到什么感兴趣的内容。

 

如果您有一个回答,那么本书现在并不太适合您,或许您可以稍后再来看看:

 

· 我完全不懂 JavaScript

· 我想要学习 OpenGLWebGL 这些比较底层的图形接口

· 我赶着加班……哎,需求又改了!


本书结构

本书针对 Three.js 的几个重要话题分章节介绍。

 

·  1 章介绍 Three.js  WebGL 的背景资料,并通过简单的例子帮助读者实现第一个

Three.js 应用。

·  2 章介绍照相机的设定。

·  3、45 章分别介绍几何形状、材质和网格,即如何在场景中添加物体。

·  6 章介绍如何实现动画效果。

·  7 章介绍如何导入外部模型。

·  8 章介绍添加光源和阴影效果。

·  9 章介绍高阶话题——着色器。

 

对于了解如何使用 Three.js 创建简单应用的读者可以跳过第 1 章,否则建议首先阅读第 1 章。对于初学者,建议按本书顺序阅读;对于比较有经验的读者,可以选择感兴趣的话题直接阅读。

寻求帮助

1. 代码

 

在每一章,本书都会用具体的例子来说明,代码可以在

https://github.com/Ovilia/ThreeExample.js 找到。书中在介绍到相关代码时,也会给出链接。

 

2. 文档

 

当你知道应该查什么关键字的时候,查阅文档是最高效的。


Three.js 的官方文档可以在 http://threejs.org/docs 找到,但是由于 Three.js 版本更新很快(在

 

本书的写作过程中,就经历了版本从 58 61 的变化,目前本书代码使用的版本是 59), 使用的时候一定要注意代码的版本和文档的版本是否一致。有些文档是过时的,和代码是不对应的,而且这份文档也不完整,这时最好参考源代码进一步了解。但即便如此,文档对于我们了解 Three.js 还是能有不少帮助。

3. Google

 

你碰到的问题很可能别人也碰到过,因此,在提问之前记得 Google

 

4. StackOverflow

 

如果你搜不到类似问题,那么在 StackOverflow 上提问吧!

 

5. 阅读源码

 

Three.js 的源码可以在 https://github.com/mrdoob/three.js/tree/master/build 找到。当怀疑文档

 

和代码不一致时,一个很有效的办法是查阅源码。当然,读源码也不是让你逐行阅读,搜索关键字即可。

当这一切都不奏效时……

 

前几天,听学长说起在微软面试时的一道题:当你遇到一个没人知道的问题时怎么办? 面试官给出了一个不错的解答:问你周围的人,碰到这样的情况他怎么办。

有时候,你得不到直接的答案,但可以间接地询问如何获取答案。我想,作为程序员,我们或多或少都会遇到似乎没人能解决的问题,你可能没有意识到,但当你不去管它,睡一觉醒来突然来了灵感时,其实这同样是种解决方法。我们会像八仙过海一样解决各种各样


看似不可能的问题,那么,下次你觉得山重水复疑无路时,记得问问你的朋友是如何寻求帮助的。

致谢

本书的顺利完成离不开很多人的帮助和关心,首先要感谢的就是我的导师肖双九博士。除了教会我对本书有直接影响的计算机图形学课程,肖老师还教会我很多受益终身的学术知识和人生哲学,而且在平时生活中也对我非常关心照顾。

Three.js 技术是我在 Intel 实习阶段学习的,因此不得不提 Intel 大学合作经理颜历女士一路以来对我的关心。她有些像我的精神导师,在我困惑迷茫的时候,给了我很多中肯的建

议。即使在我离开 Intel 后,我们也保持着联系,她也一直给予我关心和肯定,让我对自己选择的未来更有信心。

我还要特别感谢 5 位为本书作审核的同学,其中三位同学有丰富的 Three.js 开发经验,另外两名从初学者的角度为本书提出了建议。他们分别是:徐雪桥、单震宇、叶家彬;史 鑫、王佳骏。其中,徐雪桥现就读于美国 Carnegie Mellon University,具有丰富的网页开

发经验,擅长使用 JavaScript 制作动画以及数据可视化,曾参与包括 Three.js 在内的多项开源项目。其他几位是我在交大的同学,都是各自擅长领域内的牛人,非常感谢他们能够抽出很多时间参与本书的审核工作。

在此,也要感谢图灵社区提供了这样一个平台,使得本书得以面世。非常感谢图灵编辑董苗苗老师对我的悉心指导,为本书的顺利发布提供了非常重要的帮助。

此外,我最想感谢作为读者的你。这是我第一次写书,因此你对本书的支持将对我是一种莫大的鼓励!


最后,祝大家享受阅读本书的过程,创造出令人心动的应用!

 

 

 

 

  1  概述

 

本章将介绍 WebGL Three.js 的背景知识,如何下载、使用 Three.js。阅读完本章后,你将学会使用 Three.js 实现一个最简单的功能。

1.1 WebGL Three.js

 

本节介绍 WebGL Three.js 的相关概念,并通过两者实现同样功能的代码表现 Three.js 的简洁性。

 

 

1.1.1 什么是 WebGL

 

WebGL 是基于 OpenGL ES 2.0 Web 标准,可以通过 HTML5 Canvas 元素作为 DOM

 

口访问。

 

听起来挺像回事儿的,但是这是什么意思呢?


如果你了解 OpenGL,那么我解释起来就比较轻松了。WebGL 可以看做是将 OpenGL ES

OpenGL for Embedded SystemsOpenGL 嵌入式版本,针对手机、游戏机等设备相对较轻量级的版本)移植到了网页平台,像 ChromeFirefox 这些现代浏览器都实现了 WebGL 标准,使用 JavaScript 就可以用你熟悉的、类似 OpenGL 的代码编写了。

如果你不了解 OpenGL,那也没关系,因为正如 Three.js 不需要你了解 OpenGL WebGL 一样,本书也不需要你预先知道这些知识。你可以把 WebGL 简单地认为是一种网络标准,定义了一些较底层的图形接口,至于究竟多底层,稍后我们和 Three.js 代码对比来看。本书不会过多涉及 WebGL 的相关知识,如果读者想学习的话,市场上有不少相关书籍可供参考。

现在,我们知道了 WebGL 是一个底层的标准,在这些标准被定义之后,ChromeFirefox 之类的浏览器实现了这些标准。然后,程序员就能通过 JavaScript 代码,在网页上实现三维图形的渲染了。如果这对你来说还是太抽象,别着急,稍后我们会用具体的例子来说 明。

1.1.2 什么是 Three.js

 

Three.js 是一个 3D JavaScript 库。

 

如此简介的描述背后,是作者对其强大功能的自信。那么,Three.js 究竟能用来干什么呢?

Three.js 封装了底层的图形接口,使得程序员能够在无需掌握繁冗的图形学知识的情况下, 也能用简单的代码实现三维场景的渲染。我们都知道,更高的封装程度往往意味着灵活性


的牺牲,但是 Three.js 在这方面做得很好。几乎不会有 WebGL 支持而 Three.js 实现不了的情况,而且就算真的遇到这种情况,你还是能同时使用 WebGL 去实现,而不会有冲突。当然,除了 WebGL 之外,Three.js 还提供了基于 CanvasSVG 标签的渲染器,但由于通常 WebGL 能够实现更灵活的渲染效果,所以本书主要针对基于 WebGL 渲染器进行说明。

应用实例

使用 Three.js 可以实现很多酷炫的效果,比如这个 minecraft 风格的网页游戏工具库

voxel.js

 

 image.png

 

[+]查看原图

 

 精美绝伦的游戏效果

image.png

 

 


[+]查看原图

 

或是绚丽的数据可视化效果

 

 image.png

[+]查看原图

 

更多应用可以在 Three.js 官网查看。


Three.js 作者

Mr. doob  Three.js 项目发起人和主要贡献者之一,但由于 Three.js Github 上一个开源

 

项目,因此有非常多的贡献者,甚至有一天,你也可以在贡献者列表中看到自己的名字。

 

使用协议

Three.js 是基于 MIT 协议进行发布的,因此使用和发布都非常自由。

 

 

 

1.1.3 WebGL vs. Three.js

 

 

为了比较说明 Three.js 能大大简化 WebGL 的开发,我们使用最简单的例子进行比较:渲染黑色背景下的白色正方形和三角形。效果如图:

image.png 

 

Three.js 需要 30 行左右的代码:

 

  1.1.1


var renderer = new THREE.WebGLRenderer({
 
canvas: document.getElementById('mainCanvas')
 
});
 
renderer.setClearColor(0x000000); // black
 
 
 
 
var scene = new THREE.Scene();
 
 
 
 
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
 
camera.position.set(0, 0, 5);
 
camera.lookAt(new THREE.Vector3(0, 0, 0));
 
scene.add(camera);
 
 
 
 
var material = new THREE.MeshBasicMaterial({
 
color: 0xffffff // white
 
});
 
// plane
 
var planeGeo = new THREE.PlaneGeometry(1.5, 1.5);
 
var plane = new THREE.Mesh(planeGeo, material);
 
plane.position.x = 1;
 
scene.add(plane);
 
 
 
 
// triangle
 
var triGeo = new THREE.Geometry();
 
triGeo.vertices = [new THREE.Vector3(0, -0.8, 0),



如果接触过图形学知识,这里的代码应该很容易理解,如果不懂也没关系,接下来几章会进行详细说明。所以在此就不花费篇章解释这几行代码了。
以下摘录实现相同功能的 WebGL 代码,来自博客 http://learningwebgl.com/blog/?p=28。

var shaderScript = document.getElementById(id);
 
if (!shaderScript) {
 
return null;
 
}
 
 
 
 
var str = "";
 
var k = shaderScript.firstChild;
 
while (k) {
 
if (k.nodeType == 3) {
 
str += k.textContent;
 
}
 
k = k.nextSibling;
 
}
 
 
 
 
var shader;
 
if (shaderScript.type == "x-shader/x-fragment") {
 
shader = gl.createShader(gl.FRAGMENT_SHADER);
 
} else if (shaderScript.type == "x-shader/x-vertex") {
 
shader = gl.createShader(gl.VERTEX_SHADER);
 
} else {
 
return null;
 
}
 
 
 
 
gl.shaderSource(shader, str);
 
gl.compileShader(shader);
 
 
 
 
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
 
alert(gl.getShaderInfoLog(shader));
 
return null;
 
}
 
 
 
 
return shader;
 
}
 
 
 
 
var shaderProgram;
 
 
 
 
function initShaders() {
 
var fragmentShader = getShader(gl, "shader-fs");
 
var vertexShader = getShader(gl, "shader-vs");
 
 
 
 
shaderProgram = gl.createProgram();
 
gl.attachShader(shaderProgram, vertexShader);
 
gl.attachShader(shaderProgram, fragmentShader);
 
gl.linkProgram(shaderProgram);
 
 
 
 
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
 
alert("Could not initialise shaders");
 
}
 
 
 
gl.useProgram(shaderProgram);
 
 
 
 
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVe rtexPosition");
 
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
 
 
 
 
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
 
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix
");
 
}
 
 
 
 
var mvMatrix = mat4.create();
 
var pMatrix = mat4.create();
 
 
 
 
function setMatrixUniforms() {
 
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
 
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
 
}
 
 
 
 
var triangleVertexPositionBuffer;
 
var squareVertexPositionBuffer;
 
 
 
 
function initBuffers() {
 
triangleVertexPositionBuffer = gl.createBuffer();
 
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
 
var vertices = [
 
0.0,  1.0, 0.0,
 
-1.0, -1.0, 0.0,
 
1.0, -1.0, 0.0
 
];
 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
 
triangleVertexPositionBuffer.itemSize = 3;
 
triangleVertexPositionBuffer.numItems = 3;
 
 
 
 
squareVertexPositionBuffer = gl.createBuffer();
 
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
 
vertices = [
 
1.0,  1.0, 0.0,
 
-1.0,  1.0, 0.0,
 
1.0, -1.0, 0.0,
 
-1.0, -1.0, 0.0
 
];
 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
 
squareVertexPositionBuffer.itemSize = 3;
 
squareVertexPositionBuffer.numItems = 4;
 
}
 
 
 
 
function drawScene() {
 
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
 
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
 
 
 
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
 
 
 
 
mat4.identity(mvMatrix);
 
 
 
 
mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);
 
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
 
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPosi tionBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
setMatrixUniforms();
 
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
 
 
 
 
mat4.translate(mvMatrix, [3.0, 0.0, 0.0]);
 
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
 
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositi onBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
setMatrixUniforms();
 
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
 
}
 
 
 
 
function webGLStart() {
 
var canvas = document.getElementById("lesson01-canvas");
 
initGL(canvas);



从上面的代码我们不难发现,使用原生 WebGL 接口实现同样功能需要 5 倍多的代码量, 而且很多代码对于没有图形学基础的程序员是很难看懂的。由这个例子我们可以看出,使用 Three.js 开发要比 WebGL 更快更高效。尤其对图形学知识不熟悉的程序员而言,使用

Three.js 能够降低学习成本,提高三维图形程序开发的效率。

 

 

1.2 开始使用 Three.js

 

本节介绍如何下载使用 Three.js 创建你的第一个程序。

 

1.2.1 准备工作开发环境

Three.js 是一个 JavaScript 库,所以,你可以使用平时开发 JavaScript 应用的环境开发

Three.js 应用。如果你没什么偏好的话,我会推荐 Komodo IDE


调试建议使用 Chrome 或者 Firefox 浏览器。如果你使用的是 Firefox,那么 Firebug 会是你

 

必不可少的插件;如果你使用的是 Chrome,那么直接使用控制台调试即可。这些和

JavaScript 的调试是相同的,因此本书不作进一步展开。

 

下载

首先,我们需要在 Github 下载 Three.js 的代码。

 

 https://github.com/mrdoob/three.js/tree/master/build 可以

 

两个文件,前者是没有经过代码压缩的,因此适用于调试阶段;后者是经过代码压缩的, 调试起来会不太方便,但文件较小,适用于最终的发布版。保存一个文件到本地,这里我们可以选择 three.js

引用

在使用 Three.js 之前,我们需要在 HTML 文件中引用该文件:

<script type="text/javascript" src="three.js">

然后 访问方法了。

 

1.2.2 Hello, world!

 

 

接下来,我们终于要真正使用 Three.js 了!

 

首先,在 HTML  部分,需要声明外部文件 three.js 

 

<script type="text/javascript" src="js/three.js">

 



WebGL 的渲染是需要 HTML5 Canvas 元素的,你可以手动在 HTML  部分中定义

 

Canvas 元素,或者让 Three.js 帮你生成。这两种选择一般没有多大差别,我们在此手动在

HTML 中定义:

<body onload="init()">

 

<canvas id="mainCanvas" width="400px" height="300px" >

 

 JavaScript  函数 HTML 加载完

function init() {

 

// …

 

}

一个典型的 Three.js 程序至少要包括渲染器(Renderer)、场景(Scene)、照相机

Camera),以及你在场景中创建的物体。这些话题将在后面几章中进一步展开,这里我们将介绍如何快速地使用这些东西。

渲染器(Renderer

 

渲染器将 Canvas 素进行绑之前 HTML 中手动定

 

Canvas 元素,那么 Renderer 可以这样写:

var renderer = new THREE.WebGLRenderer({

 

canvas: document.getElementById('mainCanvas')

 

});


而如果想要 Three.js 生成 Canvas 元素,在 HTML 中就不需要定义 Canvas 元素,在

JavaScript 代码中可以这样写:


 

var renderer = new THREE.WebGLRenderer(); renderer.setSize(400, 300);

document.getElementsByTagName('body')[0].appendChild(renderer.domElement);



上面代码的第二行表示设置 Canvas 的宽

像素,高

像素。第三行将渲染器对应的


 

Canvas 元素添加到  中。

 

我们可以使用下面的代码将背景色(用于清除画面的颜色)设置为黑色:

renderer.setClearColor(0x000000);

场景(Scene

Three.js 中添加的物体都是添加到场景中的,因此它相当于一个大容器。一般说,场景来没有很复杂的操作,在程序最开始的时候进行实例化,然后将物体添加到场景中即可。

var scene = new THREE.Scene();


照相机(Camera

在介绍照相机设置前,我们先来简单了解下坐标系。WebGL  Three.js 使用的坐标系是右手坐标系,看起来就是这样的:


image.png 

 

这里,我们定义了一直透视投影的照相机,具体原理将在下一章中展开。


var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);

camera.position.set(0, 0, 5); scene.add(camera);


值得注意的是,照相机也需要被添加到场景中。

 

长方体

 

我们要创建一个 xyz 方向长度分别为 1  2  3 的长方体,并将其设置为红色。

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),

 

new THREE.MeshBasicMaterial({

color: 0xff0000

 

})

 

);

 

scene.add(cube);



这段代码也是比较容易理解的,虽然你现在可能还不知道 MeshBasicMaterial 是什么,但是大致可以猜测出这是一种材质,可以用来设置物体的颜色。还是要提醒下,一定要记得把创建好的长方体添加到场景中。

 

那么长度 是什在物位与

 

率等无关,简单地说,它就是一个虚拟空间的坐标系, 1 代表多少并没有实际的意义,而

 

重要的是相对长度。

 

渲染

在定义了场景中的物体,设置好的照相机之后,渲染器就知道如何渲染出二维的结果了。这时候,我们只需要调用渲染器的渲染函数,就能使其渲染一次了。

renderer.render(scene, camera);

完整代码

 

最终整的

 

1.2.1

function init() {

 

 

// renderer

 

 

var renderer = new THREE.WebGLRenderer({


canvas: document.getElementById('mainCanvas')

 

});

 

renderer.setClearColor(0x000000); // black

 

 

 

 

// scene

 

var scene = new THREE.Scene();

 

 

 

 

// camera

 

var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);

 

camera.position.set(0, 0, 5);

 

scene.add(camera);

 

 

 

 

// a cube in the scene

 

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),

 

new THREE.MeshBasicMaterial({

 

color: 0xff0000

 

})

 

);

 

scene.add(cube);

 

 

 

 

// render

 

renderer.render(scene, camera);

 

}


渲染的效果是:

image.png 

 

[+]查看原图

 

出问题了?

 

第一件事就是打开浏览器的控制台,查看报错信息。如果错误信息是

 

THREE is not defined ,那么就是页面没有成功加载 Three.js 库,很有可能的原因是文件

 

的路径写错了,一定要小心检查。

 

如果存在其他问题,请参见前言中寻求帮助部分。

 


1.3 Three.js 功能概览


 

上一节,我们了解了如何建立一个简单的 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



我们看到,Three.js 功能是十分丰富的,一时间想全部掌握有些困难。本书将从 Three.js 程序常用的功能着手,带领大家入门 Three.js


在接下来的章节中,我们将会先详细介绍照相机、几何形状、材质、物体等入门级知识; 然后介绍使用动画、模型导入、加入光照等功能;最后,对于学有余力的读者,我们将介绍着色器,用于更高级的图形渲染。

  2 照相机

 

本章将介绍照相机的概念,以及如何使用 Three.js 设置相应的参数。对于熟悉图形学照相机概念的读者,可以直接阅读 2.3 2.4 节。

2.1 什么是照相机

 

什么是照相机?这个问题似乎太简单了,用来拍照的机器。咔嚓! 可是,在图形学中照相机的概念并非如此。

我们使用 Three.js 创建的场景是三维的,而通常情况下显示屏是二维的,那么三维的场景如何显示到二维的显示屏上呢?照相机就是这样一个抽象,它定义了三维空间到二维屏幕的投影方式,用照相机这样一个类比,可以使我们直观地理解这一投影方式。

而针对投影方式的不同,照相机又分为正交投影照相机与透视投影照相机。我们需要为自己的程序选择合适的照相机。这两者分别是什么,以及两者有何差异,我们将在下节中作介绍。

2.2 正交投影 vs 透视投影

 

举个简单的例子来说明正交投影与透视投影照相机的区别。使用透视投影照相机获得的结果是类似人眼在真实世界中看到的有近大远小的效果(如下图中的(a));而使用正交投


影照相机获得的结果就像我们在数学几何学课上老师教我们画的效果,对于在三维空间内平行的线,投影到二维空间中也一定是平行的(如下图中的(b))。image.png

(a)透视投影,(b)正交投影

 

那么,你的程序需要正交投影还是透视投影的照相机呢?

 

一般说来,对于制图、建模软件通常使用正交投影,这样不会因为投影而改变物体比例; 而对于其他大多数应用,通常使用透视投影,因为这更接近人眼的观察效果。当然,照相机的选择并没有对错之分,你可以更具应用的特性,选择一个效果更佳的照相机。

2.3 正交投影照相机

参数介绍

 

THREE.OrthographicCamera(left, right, top, bottom, near, far)

 

正交投影照相机(Orthographic Camera)设置起来较为直观,它的构造函数是:

 

THREE.OrthographicCamera(left, right, top, bottom, near, far)


这六个参数分别代表正交投影照相机拍摄到的空间的六个面的位置,这两个面围成一个长方体,我们称其为视景体Frustum)。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,而视景体外的物体会在显示之前被裁减掉。

 

 

 image.png

 

 

[+]查看原图

 

为了保持照相机的横竖比例,需要保证 (right – left)  (top – bottom) 的比例与 Canvas

 

宽度与高度的比例一致。


都是指机位,而其后的物

 

体,因此这两个值应该均为正值。为了保证场景中的物体不会因为太近或太远而被照相机

 

忽略,一 的值设置得较 far 大,的位

 

决定。

 

实例说明

 

 

下面,我们通过一个具体的例子来解释正交投影照相机的设置。

 

  2.3.1

 

基本设置

设置照相机:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, –1.5, 1, 10);

camera.position.set(0, 0, 5); scene.add(camera);

在原边长 的正果做们使

 

而不是实心的材质,以便看到正方体后方的边:

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshBasicMaterial({

color: 0xff0000, wireframe: true

})


);

 

scene.add(cube);

得到的效果是:

image.png

我们看到正交投影的结果是一个正方形,后面的边与前面完全重合了,这也就是正交投影与透视投影的区别所在。

长宽比例

 

这里,我们的 Canvas 宽度是 400px ,高度是 300px ,照相机水平方向距离 4 ,垂直方向

 

距离 3 ,因此长宽比例保持不变。为了试验长宽比例变化时的效果,我们将照相机水平方

 

向的距离减小为 2 

var camera = new THREE.OrthographicCamera(-1, 1, 1.5, –1.5, 1, 10);

得到的结果是水平方向被拉长了:


image.png 

 

照相机位置

接下来,我们来看看照相机位置对渲染结果的影响。在之前的例子中,我们将照相机设置

 

(0, 0, 5) 位置,而由于照相机默认是面向 z 轴负方向放置的,所以能看到在原点处的

 

正方将照 1位:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, –1.5, 1, 10);

 

camera.position.set(1, 0, 5);

得到的效果是物体看上去向左移动了:


image.png 

 

仔细想一下的话,这也不难理解。就好比你人往右站了,看起来物体就相对往左移动了。

 

那么设置 是相果不

 

那么会产生什么效果呢?下面,我们将原本的参数 (-2, 2, 1.5, -1.5, 1, 10) 改为 (-1,

 

3, 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);

得到的结果是:


image.png 

 

细心的读者已经发现,这与之前向右移动照相机得到的效果是等价的。

 

换个角度看世界

到现在为止,我们使用照相机都是沿 z 轴负方向观察的,因此看到的都是一个正方形。现在,我们想尝试一下仰望这个正方体。我们已经学会设置照相机的位置,不妨将其设置在

(4, -3, 5) 处:

camera.position.set(4, –3, 5);

但是现在照相机沿 z 轴负方向观察的,因此观察不到正方体,只看到一片黑。我们可以通

 

 loolat 函数指看着原点向:

camera.lookAt(new THREE.Vector3(0, 0, 0));


这样我们就能过仰望正方体啦:


image.png 

 

不过 lookAt 函数 的实例,千万别写成

 

camera.lookAt(0, 0, 0) ,否则非但不能得到理想的效果,而且不会报错,使你很难找到

 

问题所在。

 

现在,恭喜你学会设置正交照相机了!虽然它看起来较为简单,但是加入动画、交互等因素后,可以为你的应用程序增色不少的!

前面第一章就完了哟,感谢支持天才写手!继续下一章节学习吧!

 

    关键字:

天才代写-代写联系方式