three.js 入門詳解(一)

image

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 下載地址

1.3.2 目錄結構

image

  • 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以前,首先在 <head>部分,須要引入外部文件 Three.js
<head>
    <script type="text/javascript" src="three.js"></script>
</head>
WebGL 的渲染是須要HTML5 中的 Canvas元素的,你能夠手動在HTML的 <body>部分中使用canvas標籤,或者讓Three.js幫你生成。這兩種選擇,通常沒有多大差異。咱們先手動定義一個canvas標籤:
<body onload="init();">
    <canvas id="canvasId" width="800" height="600"></canvas>
</body>
在js裏面定義一個函數,將全部執行的代碼放在函數裏,在html加載完成後,執行該函數
function init{
    // 全部須要執行的代碼
}

一個典型的Three.js程序,至少應該包括四個部分:渲染器(renderer)場景(scene)相機(camera)以及場景中建立的物體javascript

2.1 渲染器(renderer)

渲染器決定了 渲染的結果應該畫在 頁面的什麼元素上面,而且 以怎樣的方式來繪製

渲染器將會和canvas元素進行綁定,若是以前<html>標籤中,定義了id爲canvasId的canvas標籤,那麼renderer能夠這樣寫:html

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軸的方向就是屏幕由裏往外的方向

image

這裏咱們定義一個 透視相機(相機也須要添加到場景中):
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
// 設置相機的位置
camera.position.set(0,0,5);
// 將相機添加到場景中
scene.add(camera);

2.4 建立一個物體

這裏咱們先介紹一個長方體,建立一個x、y、z方向長度分別爲一、二、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(); 表示的是物體的材質java

    • 你能夠在裏面設置物體的顏色
var material = new THREE.MeshBasicMaterial({
    color: 0xff0000;
});
  • 必定不要忘了,將物體添加到場景

2.5 渲染

在定義了場景中的物體,設置好的照相機以後,渲染器就知道如何渲染出二維的結果了。這時候,咱們只須要調用渲染器的渲染函數,就能使其渲染一次了。
renderer.render(scene, camera);

2.6 完整代碼

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>長方體</title>
    <script src="three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // canvas元素設置寬高
            renderer.setSize = (800, 600);
            // 渲染器對應的Canvas元素添加到<body>中。
            document.body.appendChild(renderer.domElement);
            // 清除畫面的顏色
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            // 定義一個透視相機
            var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
            // 設定相機的位置
            camera.position.set(0, 0, 5);
            // 將相機添加到場景中
            scene.add(camera);

            // 物體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), new THREE.MeshBasicMaterial({
                color: 0xff0000
            }));
            scene.add(cube);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>
</html>
  • 效果圖

image
canvas元素的默認寬高爲300/150python

3. Three.js功能概覽

下面介紹下Three.js官網文檔中的一些重要的對象,在你須要尋求幫助時,就可以知道關鍵詞是什麼。
  • Cameras(照相機,控制投影方式)git

    • Camera
    • OrthographicCamera
    • PerspectiveCamera
  • Core(核心對象)程序員

    • BufferGeometry
    • Clock(用來記錄時間)
    • EventDispatcher
    • Face3
    • Face4
    • Geometry
    • Object3D
    • Projector
    • Raycaster(計算鼠標拾取物體時頗有用的對象)
  • Lights(光照)github

    • Light
    • AmbientLight
    • AreaLight
    • DirectionalLight
    • HemisphereLight
    • PointLight
    • SpotLight
  • Loaders(加載器,用來加載特定文件)web

    • 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))。

image

通常說來,對於製圖、建模軟一般使正交投影,這樣不會由於投影而改變物體比例;而對於其餘大多數應用,一般使用 透視投影,由於這更接近人眼的觀察效果。固然,照相機的選擇並無對錯之分,你能夠更具應用的特性,選擇一個效果更佳的照相機。

4.3 正交投影照相機

4.3.1 參數介紹

正交投影照相機( Orthographic Camera)
THREE.OrthographicCamera(left, right, top, bottom, near, far)
這六個參數分別表明正交投影照相機拍攝到的空間的六個面的位置,這六個面圍成一個長方體,咱們稱其 視景體(Frustum)。只有在視景體內部(下圖中的灰色部分)的物體纔可能顯示在屏幕上,而視景體外的物體會在顯示以前被裁減掉。

image

爲了保持照相機的橫豎比例,須要保證 (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);
  • 效果圖:

image

  • 咱們看到正交投影的結果是一個正方形,後面的邊與前面徹底重合了,這也就是正交投影與透視投影的區別所在。

長寬比例

這裏,咱們的Canvas寬度是800px,高度是600px,照相機水平方向距離4,垂直方向距離3,所以長寬比例保持不變。爲了試驗長寬比例變化時的效果,咱們將照相機水平方向的距離減少爲2(right-left = 2):
var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
  • 效果圖(此時水平方向的距離就被拉長了):

image

照相機位置

接下來,咱們來看看照相機位置對渲染結果的影響。在以前的例子中,咱們將照相機設置在(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

  • 其實照相機就比如人的眼睛,當咱們身體往右移動的時候,看到的物體就好像向左移了。
正交投影攝像機在設置時,是否須要保證 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);
  • 效果圖(與以前相機向右的效果是同樣的)

image

換個角度

到目前爲止,咱們使用照相機,都是 沿着Z軸負方向觀察的,所以看到的都是一個正方形,如今咱們嘗試一下 仰望這個正方體,改變照相機的位置:
// x軸:4;  y軸:-3;  z軸:5
camera.position.set(4, -3, 5);
照相機默認是沿着z軸的負方向觀察的,所以觀察不到正方體,只看到一片黑。咱們能夠經過 lookAt函數指定它 看着原點方向

image

camera.lookAt(new THREE.Vector3(0, 0, 0));
  • 效果圖:

image

  • 注意:lookAt函數接收的是一個THREE.Vector3的實例千萬不能寫成camera.lookAt(0,0,0)

4.4 透視投影照相機

4.4.1 參數介紹

透視投影照相機( Perspective Camera)
THREE.PerspectiveCamera(fov, aspect, near, far)
讓咱們經過一張透視照相機投影的圖來了解這些參數。

image

  • 透視圖中,灰色的部分是視景體,是可能被渲染的物體所在的區域。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);
  • 效果圖:

image

  • 對比正交透視照相機下正方形的效果,透視投影能夠看到所有的12條邊,並且有近大遠小的效果,這也就是與正交投影的區別。

豎直張角

  • 接下來,咱們來看下fov的改變對渲染效果的影響。咱們將原來的45改成60
var camera = new THREE.PerspectiveCamera(60, 800 / 600, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
  • 效果圖:

image

  • 爲何正方體顯得更小了呢?咱們從下面的側視圖來看,雖然正方體的實際大小並未改變,可是將照相機的豎直張角設置得更大時,視景體變大了,於是正方體相對於整個視景體的大小就變小了,看起來正方形就顯得變小了。

image

  • 注意,改變fov不會起畫面橫豎比例的變化,而改變aspect改變橫豎比例。

5. 點、線、面

5.1 3D世界的組成

在計算機世界裏,3D世界由點組成,兩個點能組成一條直線,三個不在一條直線上的點,就能組成一個三角面, 無數的三角面就能組成 各類各樣的物體,以下圖:

image

  • 咱們一般把這種網絡模型叫作Mesh模型。給物體貼上皮膚,或者專業點就叫作紋理,那麼這個物體就活靈活現了。最後無數的物體就組成了咱們的3D世界。

5.2 在Three.js中定義一個點

在三維空間中的某一個點能夠用一個座標點來表示。一個座標點由 x, y, z三個份量構成。在three.js中,點能夠在右手座標系中表示:

空間幾何中,點能夠用一個向量來表示,在Three.js中也是用一個向量來表示的

THREE.Vector3 = function ( x, y, z ) {

this.x = x || 0;
this.y = y || 0;
this.z = z || 0;

};
  • 咱們來分析這段代碼:前面咱們已經知道了THREE是Three.js引擎的一個全局變量。只要你想用它,就能夠在任何地方用它。
  • 那麼THREE.Vector3呢,就是表示Vector3是定義在THREE下面的一個。之後要用Vector3,就必須要加THREE前綴。固然Three.js的設計者,也能夠不加THREE這個前綴,可是他們預見到,Three.js引擎中會有不少類型,最好給這些類型加一個前綴,以避免與開發者的代碼產生衝突。
  • THREE.Vector3被賦值爲一個函數。這個函數有3個參數,分別表明x座標y座標z座標的份量。函數體內的代碼將他們分別賦值給成員變量x,y,z。看看上面的代碼,中間使用了一個「||」(或)運算符,就是當x=null或者undefine時,this.x的值應該取0

5.3 點的操做

在3D世界中 能夠用 THREE.Vector3D來表示。
  • 如今來看看怎麼定義個點,假設有一個點x=4,y=8,z=9。你能夠這樣定義它:
var point1 = new THREE.Vecotr3(4,8,9);
  • 另外你也可使用set方法,代碼以下:
var point1 = new THREE.Vector3();

point1.set(4,8,9);

5.4 繪製一條線段

兩個不重合的點可以決定一條直線。在three.js中,也能夠經過定義兩個點,來畫一條直線。
  • 一、首先,聲明一個幾何體geometry
  • 幾何體裏面有個vertices變量,能夠用來存放點
var geometry = new THREE.Geometry();
// 幾何體裏面有個vertices變量,能夠用來存放點
  • 二、定義一種線條的材質,使用THREE.LineBasicMaterial類型來定義,它接受一個集合做爲參數,其原型以下:
THREE.LineBasicMaterial(parameters);
  • parameters 是定義材質外觀的對象,它包含多個屬性來定義材質,這些屬性是:

    • Color 線條的顏色,用16進製表示,默認都是白色
    • Linewidth 線條的寬度,默認是1個單位寬度
    • Linecap 線條兩端的外觀,默認是圓角端點,當線條較粗的時候才能看到效果
    • Linejoin 兩個線條的鏈接點處的外觀,默認是「round」,表示圓角。
    • VertexColors 定義線條材質是否使用頂點顏色,這是一個boolean值。意思是,線條各部分的顏色會根據頂點的顏色來進行插值。
    • Fog 定義材質的顏色是否受全局霧效的影響。
  • 咱們這裏使用了頂點顏色 vertexColors: THREE.VertexColors,就是線條的顏色會根據頂點來計算。
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
  • 注意: 關於線寬的坑,WebGLRender渲染方式是不之持繪製線寬的,要想支持,須要將渲染方式設置爲CanvasRenderer
  • 三、接下來,定義兩種顏色,分別表示線條兩個端點的顏色,
var color1 = new THREE.Color( 0x444444 ),
    color2 = new THREE.Color( 0xFF0000 );
  • 四、定義2個頂點的位置,並放到geometry中,代碼以下:
var p1 = new THREE.Vector3(-100,0,100);
var p2 = new THREE.Vector3(100,0,-100);

geometry.vertices.push(p1);
geometry.vertices.push(p2);
  • 五、爲4中定義的2個頂點,設置不一樣的顏色,代碼以下所示:
geometry.colors.push( color1, color2 );
  • geometry中colors表示頂點的顏色,必須材質中vertexColors等於THREE.VertexColors時,顏色才有效,若是vertexColors等於THREE.NoColors時,顏色就沒有效果了。那麼就會去取材質中color的值,這個很重要。
  • 六、定義一條線。
  • 定義線條,使用THREE.Line類,代碼以下所示:
var line = new THREE.Line( geometry, material, THREE.LinePieces );
  • 第一個參數是幾何體geometry,裏面包含了2個頂點和頂點的顏色
  • 第二個參數是線條的材質,或者是線條的屬性,表示線條以哪一種方式取色。
  • 第三個參數是一組點的鏈接方式。
  • 七、而後,將這條線加入到場景中,代碼以下:
scene.add(line);
  • 八、總體代碼:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

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

    <script type="text/javascript">
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // 設定渲染器尺寸
            renderer.setSize(800, 600);
            // 添加到dom
            document.body.appendChild(renderer.domElement);
            // 重繪時顏色
            renderer.setClearColor(0xffffff);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            // 設定相機位置
            camera.position.set(0, -25, 0);
            // 相機看向
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 定義一個物體
            // new 一個模型
            var geometry = new THREE.Geometry();
            // 定義模型的類型是線段  而且設置其材質
            var material = new THREE.LineBasicMaterial({
                // 使用頂點顏色
                vertexColors: true
            });
            // 定義兩個顏色
            var color1 = new THREE.Color(0x444444),
                color2 = new THREE.Color(0xff0000);

            // 新建兩個點
            var p1 = new THREE.Vector3(-1, 0, 1);
            var p2 = new THREE.Vector3(1, 0, -1);

            // 將新建的兩個點添加到幾何體中
            geometry.vertices.push(p1);
            geometry.vertices.push(p2);

            // 將兩個顏色添加到幾何體中
            geometry.colors.push(color1, color2);

            // new 一條線
            var line = new THREE.Line(geometry, material, THREE.LinePieces);
            scene.add(line);

            // 渲染
            renderer.render(scene, camera);

        }
    </script>
</head>

<body onload="init()">

</body>

</html>
  • 效果圖:

image

5.5 線條的深度理解

在Threejs中,一條線由點,材質和顏色組成。
  • 點由THREE.Vector3表示,Threejs中沒有提供單獨畫點的函數,它必須被放到一個THREE.Geometry形狀中,這個結構中包含一個數組vertices,這個vertices就是存放無數的點(THREE.Vector3)的數組
  • 一、爲了繪製一條直線,首先咱們須要定義兩個點
var p1 = new THREE.Vector3( -1, 0, 1 );
var p2 = new THREE.Vector3( 1, 0, -1 );
  • 二、聲明一個THREE.Geometry,並把點加進去
var geometry = new THREE.Geometry();
geometry.vertices.push(p1);
geometry.vertices.push(p2);
  • geometry.vertices的可以使用push方法,是由於geometry.vertices是一個數組。這樣geometry中就有了2個點了。
  • 三、而後咱們須要給線加一種材質,THREE.LineBasicMaterial
var material = new THREE.LineBasicMaterial();
  • 四、最終咱們經過THREE.Line繪製了一條線:
var line = new THREE.Line( geometry, material, THREE.LinePieces );

5.6 繪製網格線

咱們要畫一個網格的座標,那麼咱們就應該找到線的點。把網格虛擬成正方形,在正方形邊界上找到幾個等分點,用這些點兩兩鏈接,就可以畫出整個網格來。
  • 一、定義兩個點
// 在x軸上定義兩個點p1(-500,0,0),p2(500,0,0)。
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ));
geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ));
  • 二、算法

    • 這兩個點決定了x軸上的一條線段,將這條線段複製20次,分別平行移動到z軸的不一樣位置,就可以造成一組平行的線段。
    • 同理,將p1p2這條線先圍繞y軸旋轉90度,而後再複製20份,平行於z軸移動到不一樣的位置,也能造成一組平行線。
for ( var i = 0; i <-= 20; i ++ ) {
    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 }));
    line.position.z = ( i * 50 ) - 500;
    scene.add( line );

    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ));
    line.position.x = ( i * 50 ) - 500;
    line.rotation.y = 90 * Math.PI / 180;   //  旋轉90度
    scene.add( line );

}
  • 三、完整代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

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

    <script type="text/javascript">
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // 設定渲染器尺寸
            renderer.setSize(800, 600);
            // 添加到dom
            document.body.appendChild(renderer.domElement);
            // 重繪時顏色
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            // 設定相機位置
            camera.position.set(0, -25, 0);
            // 相機看向
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 定義一個幾何體
            var geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(-2, 0, 0));
            geometry.vertices.push(new THREE.Vector3(2, 0, 0));
            // for循環出來六條線段
            for (var i = 0; i <= 5; i++) {
                // 定義豎着的線段
                var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({
                    color: 0xffffff,
                }));
                // 每條線段之間的間隔爲0.8,-2是爲了達到田字格的效果
                line.position.z = (i * 0.8) - 2;
                scene.add(line);

                // 定義橫着的線段
                var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({
                    color: 0xffffff,
                    opacity: 0.2
                }));
                line.position.x = (i * 0.8) - 2;
                line.rotation.y = 90 * Math.PI / 180;
                scene.add(line);

                // 渲染
                renderer.render(scene, camera);

            }
        }
    </script>
</head>

<body onload="init()">

</body>

</html>
  • 效果圖:

image

6. 幾何形狀

在建立物體時,須要傳入兩個參數,一個是 幾何形狀(Geometry),另外一個是 材質(Material),這一章將着重介紹幾何形狀的建立,第6章介紹材質,第7章介紹如何使用二者建立網格。
  • 幾何形狀(Geometry)最主要的功能是儲存了一個物體的頂點信息。WebGL須要程序員指定每一個頂點的位置,而在Three.js中,能夠經過指定一些特徵來建立幾何形狀,例如使用半徑建立一個球體,從而省去程序員一個個指定頂點的工做量。
  • 本章節將分別介紹立方體、平面、球體、圓柱體、四面體、八面體等幾何形狀,以及以三維文字做爲幾何形狀的方法。本節還會介紹經過手動定義 頂點位置面片信息組成幾何形狀。

6.1 基本幾何形狀

6.1.1 立方體

雖然這形狀的名字叫作立方體( CubeGeometry),但實際上是長方體,也就是長寬高能夠設置不一樣的值:
new THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
  • 這裏,widthx方向上的長度;heighty方向上的長度;depthz方向上的長度;後三個參數分別是在三個方向上的分段數,如widthSegments爲3的話,表明x方向上水平分爲三份。通常狀況下不須要分段的話,能夠不設置後三個參數,後三個參數的缺省值爲1。其餘幾何形狀中的分段也是相似的,下面不作說明。

長寬高

  • 建立立方體直觀簡單,如:new THREE.CubeGeometry(1, 2, 3);能夠建立一個x方向長度爲1,y方向長度爲2,z方向長度爲3的立方體。
// 調用渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 600);
document.body.appendChild(renderer.domElement);
renderer.setClearColor(0x000000);

// 調用場景
var scene = new THREE.Scene();

// 調用相機
var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
camera.position.set(25, 25, 25);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

// 新建一個幾何體(長方體)
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), new THREE.MeshBasicMaterial({
    color: 0xffff00,
    wireframe: true
}));

scene.add(cube);
  • 爲了更好地表現參數效果,咱們在場景中用長度爲3紅、綠、藍線段分別表示x、y、z三個軸(這裏不須要深究,後面會詳細介紹):
// 封裝一個座標系函數
function drawAxes(scene) {
    // x-axis
    var xGeo = new THREE.Geometry();
    xGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    xGeo.vertices.push(new THREE.Vector3(3, 0, 0));
    var xMat = new THREE.LineBasicMaterial({
        color: 0xff0000
    });
    var xAxis = new THREE.Line(xGeo, xMat);
    scene.add(xAxis);

    // y-axis
    var yGeo = new THREE.Geometry();
    yGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    yGeo.vertices.push(new THREE.Vector3(0, 3, 0));
    var yMat = new THREE.LineBasicMaterial({
        color: 0x00ff00
    });
    var yAxis = new THREE.Line(yGeo, yMat);
    scene.add(yAxis);

    // z-axis
    var zGeo = new THREE.Geometry();
    zGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    zGeo.vertices.push(new THREE.Vector3(0, 0, 3));
    var zMat = new THREE.LineBasicMaterial({
        color: 0x00ccff
    });
    var zAxis = new THREE.Line(zGeo, zMat);
    scene.add(zAxis);
}

// 在init 函數裏調用這個函數 便可在屏幕上顯示一個座標系了
drawAxes(scene);
  • 在設置材質,並添加到場景以後具體的效果是:

image

  • 物體的默認位置原點,對於立方體而言,是其幾何中心在原點的位置。

分段

  • 根據THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments),的後三個參數,爲這個長方體分段:
// x軸分兩段  y軸分兩段 z軸分三段
new THREE.CubeGeometry(1, 2, 3, 2, 2, 3)
  • 效果圖:

image

  • 注意這個分段是對六個面進行分段,而不是對立方體的體素分段,所以在立方體的中間是不分段的,只有六個側面被分段。

6.1.2 平面

這裏的平面( PlaneGeometry)實際上是一個長方形,而並不是是數學意義上無限大的平面:
new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
  • 其中,widthx方向上的長度;heighty方向上的長度;後兩個參數一樣表示分段
  • new THREE.PlaneGeometry(2, 4);建立的平面在x軸和y軸所在平面內:
var plane = new THREE.Mesh(
    new THREE.PlaneGeometry(2, 4), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(plane);
  • 效果圖:

image

  • 若是須要建立的平面在x軸和z軸所在的平面內,能夠經過物體的旋轉來實現,具體的作法將在下面章節介紹到。

6.1.3 球體

球體( SphereGeometry)的構造函數是:
new THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
  • 其中,radius半徑segmentsWidth表示經度上的切片數segmentsHeight表示緯度上的切片數phiStart表示經度開始的弧度phiLength表示經度跨過的弧度thetaStart表示緯度開始的弧度thetaLength表示緯度跨過的弧度

分段

  • 首先,咱們來理解下segmentsWidthsegmentsHeight。使用var sphere = new THREE.SphereGeometry(2, 8, 6)能夠建立一個半徑爲2經度劃分紅8份,緯度劃分紅6份的球體
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果圖:

image

  • new THREE.SphereGeometry(2, 8, 16)的效果如圖:

image

  • new THREE.SphereGeometry(3, 18, 12)的效果如圖:

image

  • segmentsWidth至關於經度被切成了幾瓣,而segmentsHeight至關於緯度被切成了幾層。由於在圖形底層的實現中,並沒有曲線的概念,曲線都是由多個折線近似構成的。對於球體而言,當這兩個值較大的時候,造成的多面體就能夠近似看作是球體了。

經度弧度

  • new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3)表示起始經度爲Math.PI / 6,經度跨度爲Math.PI / 3
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果圖:

image

  • 值得注意的是,這裏的SegmentsWidth8意味着對於經度從Math.PI / 2跨過Math.PI / 3區域內劃分爲8塊,而不是整個球體的經度劃分紅8塊後再判斷在此經度範圍內的部分。

緯度弧度

  • 理解了經度以後,緯度能夠同理理解。new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3)意味着緯度從Math.PI / 6跨過Math.PI / 3
var sphere = new THREE.Mesh(
    // 經度起始弧度爲0度,經度跨度爲 180*2
    new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果圖:

image

  • 咱們再來看一個經度緯度都改變了起始位置和跨度的例子:new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2)
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果圖:

image

6.1.4 圓形

圓形( CircleGeometry)能夠建立 圓形或者扇形,其構造函數是:
new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength)
  • 這裏的參數跟繪製圓是同樣的,咱們再來熟悉一下。radius是半徑;segments表示切片數;thetaStart表示緯度開始的弧度thetaLength表示緯度跨過的弧度
  • 看個例子: new THREE.CircleGeometry(3, 18, Math.PI / 3, Math.PI / 3 * 4)能夠建立一個在x軸和y軸所在平面的三分之二圓的扇形:
var circle = new THREE.Mesh(
    new THREE.CircleGeometry(2, 18, Math.PI / 3, Math.PI / 3 * 4), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(circle);
  • 效果圖:

image

6.1.5 圓柱體

圓柱體( CylinderGeometry)的構造函數是:
new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
  • 其中,radiusTopradiusBottom分別是頂面和底面的半徑,由此可知,當這兩個參數設置爲不一樣的值時,實際上建立的是一個圓臺;height是圓柱體的高度radiusSegmentsheightSegments可類比球體中的分段,一個表示底面、頂面的分段,另外一個表示環面的分段;openEnded是一個布爾值,表示是否沒有頂面和底面,缺省值爲false,表示有頂面和底面。

標準圓柱體

  • new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3)建立一個頂面與底面半徑都爲2,高度爲4的圓柱體:
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果圖:

image

圓臺

  • 頂面、底面半徑不一致的時候,便是一個圓臺。將底面半徑設爲2建立一個圓臺:new THREE.CylinderGeometry(1.5, 2, 3, 18, 3)
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 2, 3, 18, 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果圖:

image

無底面、頂面

  • openEndedtrue的時候,將無底面、頂面。new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true)將建立一個沒有頂面與底面的圓柱:
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果圖:

image

6.1.6 正四面體、正八面體、正二十面體

正四面體( TetrahedronGeometry)、正八面體( OctahedronGeometry)、正二十面體( IcosahedronGeometry)的構造函數較爲相似,分別爲:
// 正四面體
new THREE.TetrahedronGeometry(radius, detail)
// 正八面體
new THREE.OctahedronGeometry(radius, detail)
// 正二十面體
new THREE.IcosahedronGeometry(radius, detail)
  • 其中,radius是半徑;detail是細節層次(Level of Detail)的層數,對於大面片數模型,能夠控制在視角靠近物體時,顯示面片數多的精細模型,而在離物體較遠時,顯示面片數較少的粗略模型。這裏咱們不對detail多做展開,通常能夠對這個值缺省。

正四面體

  • new THREE.TetrahedronGeometry(2.5)建立一個半徑2.5的正四面體:
var tetrahedron = new THREE.Mesh(
    new THREE.TetrahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(tetrahedron);
  • 效果圖:

image

正八面體

  • new THREE.OctahedronGeometry(2.5)建立一個半徑爲2.5的正八面體:
var octahedron = new THREE.Mesh(
    new THREE.OctahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(octahedron);
  • 效果圖:

image

正二十面體

  • new THREE.IcosahedronGeometry(2.5)建立一個半徑爲2.5的正二十面體:
var icosahedron = new THREE.Mesh(
    new THREE.IcosahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(icosahedron);
  • 效果圖:

image

6.1.7 圓環面

圓環面( TorusGeometry)就是甜甜圈的形狀,其構造函數是:
new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)

image

  • 其中,radius是圓環半徑;tube是管道半徑;radialSegmentstubularSegments分別是兩個分段數,詳見上圖;arc是圓環面的弧度,缺省值爲Math.PI * 2

粗糙圓環面

  • new THREE.TorusGeometry(2, 0.7, 4, 8)建立一個粗糙的圓環面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 4, 8),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果圖:

image

精細圓環面

  • new THREE.TorusGeometry(2, 0.7, 12, 18)建立一個較爲精細的圓環面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 12, 18),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果圖:

image

部分圓環面

  • new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2)建立部分圓環面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果圖:

image

6.1.8 圓環結

若是說圓環面是甜甜圈,那麼圓環結( TorusKnotGeometry)就是打告終的甜甜圈,其構造參數爲:
new THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments, p, q, heightScale)
  • 前四個參數在圓環面中已經有所介紹,pq是控制其樣式的參數,通常能夠缺省,若是須要詳細瞭解,請學習圓環結的相關知識heightScale是在z軸方向上的縮放。
  • new THREE.TorusKnotGeometry(2, 0.5, 32, 8) 默認樣式的圓環結:
var torus = new THREE.Mesh(
    new THREE.TorusKnotGeometry(1.6, 0.4, 32, 8),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果圖:

image

6.2 文字形狀

文字形狀( TextGeometry)能夠用來建立三維的文字形狀。

6.2.1 下載使用

使用文字前,須要下載和引用額外的字體庫。字體庫在 three.js Github master/examples/fonts目錄下,下載裏面的 json文件,放在你的目錄下,而後加載。

image

  • 這裏,咱們就以helvetiker字體爲例。咱們在剛剛的字體庫目錄下,下載helvetiker_regular.typeface.json文件放在你的目錄下,而後用如下方法加載:
// 調用一個字體加載函數
var loader = new THREE.FontLoader();
loader.load('helvetiker_regular.typeface.json', function(font) {
    var mesh = new THREE.Mesh(
        new THREE.TextGeometry('Hello', {
            font: font,
            size: 1,
            height: 1
        }), 
        new THREE.MeshBasicMaterial({
            color: 0xffff00,
            wireframe: true
        })
    );
    scene.add(mesh);
    // 寫在loader函數裏面 不然不顯示
    renderer.render(scene,camera);
});
  • 注意:

    • 以前用的73dev版本的three.js,執行代碼的時候發現報錯,多是尚未添加這個功能,因此建議去下載最新版本的three.js
    • json配置文件,須要在本地服務器打開,推薦使用webstorm編輯器,由於它打開html文件時,就是以本地服務器的方式打開的。或者在cmd命令行中輸入live-server,但須要配置,具體方法請點這裏

6.2.2 參數介紹

建立文字形狀的流程和以前介紹的基本幾何形狀是相似的,其構造函數是:
new THREE.TextGeometry(text, parameters)
  • 其中,text是要顯示的文字字符串,parameters是如下參數組成的對象:

    • size:字號大小,通常爲大寫字母的高度
    • height:文字的厚度
    • curveSegments:弧線分段數,使得文字的曲線更加光滑
    • font:字體,默認是'helvetiker',需對應引用的字體文件
    • weight:值爲'normal''bold',表示是否加粗
    • style:值爲'normal''italics',表示是否斜體
    • bevelEnabled:布爾值,是否使用倒角,意爲在邊緣處斜切
    • bevelThickness:倒角厚度
    • bevelSize:倒角寬度

6.2.3 示例代碼

建立一個三維文字 new THREE.TextGeometry("hello", {size: 1, height: 1})
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>hello</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init()">
    <script>
        function init() {
            // 調用一個渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 調用場景
            var scene = new THREE.Scene();

            // 調用相機
            var camera = new THREE.OrthographicCamera(-4, 4, 3, -3, 0.1, 100);
            camera.position.set(5, 5, 20);
            camera.lookAt(new THREE.Vector3(1.1, 0, 0));
            scene.add(camera);

            // 定義材質
            var material = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                wireframe: true
            });

            // 加載文字模板
            var loader = new THREE.FontLoader();
            loader.load('helvetiker_regular.typeface.json', function(font) {
                // 中文字符不能解析
                var mesh = new THREE.Mesh(new THREE.TextGeometry('hello', {
                    font: font,
                    size: 1,
                    height: 1
                }), material);
                scene.add(mesh);
                // 渲染必定要在load函數裏面
                renderer.render(scene, camera);
            })
        }
    </script>
</body>
</html>
  • 效果圖:

image

  • 咱們能夠改變材質和添加光照來改變顯示效果(燈光、材質沒必要深究,後面會細講)
// 將材質改成lambert材質
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});

// 加上一束方向光
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 0, 0.5);
scene.add(light);
  • 效果圖:

image

  • 這裏只是給你們看了一個效果,具體材質、燈光的原理不要去深究,直接跳過,看下面的知識點。

6.3 自定義形狀

對於Three.js沒有提供的形狀,能夠經過自定義形狀來建立。
  • 因爲自定義形狀須要手動指定每一個頂點位置,以及頂點鏈接狀況,若是該形狀很是複雜,程序員計算量就會比較大。這種狀況,建議使用建模工具,建立好以後,再經過three.js導入到場景中,這樣會十分高效、方便。
  • 自定義形狀使用的是Geometry類,它是其餘如CubeGeometry、SphereGeometry等幾何形狀的父類,其構造函數是:
new THREE.Geometry()
  • 咱們以建立一個梯臺爲例,首先,初始化一個幾何形狀,而後設置頂點位置以及頂點鏈接狀況。

    • 頂面建立4個點,底面建立4個點,按照順時針的順序逐個建立
    • geometry建立點的時候都是push到數組vertices裏面的
    • 因此這8個點,按照順序都有一個對應的索引值
    • 利用Face3的方法將3點連成一個三角面

image

  • 看代碼
// 初始化幾何形狀
var geometry = new THREE.Geometry();

// 設置頂點的位置 
// 頂部4個點
geometry.vertices.push(new THREE.Vector3(-1, 2, -1));
geometry.vertices.push(new THREE.Vector3(1, 2, -1));
geometry.vertices.push(new THREE.Vector3(1, 2, 1));
geometry.vertices.push(new THREE.Vector3(-1, 2, 1));
// 底部4頂點
geometry.vertices.push(new THREE.Vector3(-2, 0, -2));
geometry.vertices.push(new THREE.Vector3(2, 0, -2));
geometry.vertices.push(new THREE.Vector3(2, 0, 2));
geometry.vertices.push(new THREE.Vector3(-2, 0, 2));

// 設置頂點鏈接狀況
// 頂面
geometry.faces.push(new THREE.Face3(0, 1, 3));
geometry.faces.push(new THREE.Face3(1, 2, 3));
// 底面
geometry.faces.push(new THREE.Face3(4, 5, 6));
geometry.faces.push(new THREE.Face3(5, 6, 7));
// 四個側面
geometry.faces.push(new THREE.Face3(1, 5, 6));
geometry.faces.push(new THREE.Face3(6, 2, 1));
geometry.faces.push(new THREE.Face3(2, 6, 7));
geometry.faces.push(new THREE.Face3(7, 3, 2));
geometry.faces.push(new THREE.Face3(3, 7, 0));
geometry.faces.push(new THREE.Face3(7, 4, 0));
geometry.faces.push(new THREE.Face3(0, 4, 5));
geometry.faces.push(new THREE.Face3(0, 5, 1));
  • 效果圖:

image

  • 總結:

    • 須要注意的是,new THREE.Vector3(-1, 2, -1)建立一個矢量,做爲頂點位置追加到geometry.vertices數組中。
    • 而由new THREE.Face3(0, 1, 3)建立一個三個頂點組成的面片,追加到geometry.faces數組中。三個參數分別是四個頂點在geometry.vertices中的序號。

7. 材質

材質( material),是獨立於物體頂點信息以外的與渲染效果相關的屬性。經過設置材質能夠改變物體顏色、紋理貼圖、光照模式等。
  • 下面將會爲你們介紹基本材質兩種基於光照模型材質法向量做爲材質圖像做爲材質

7.1 基本材質

使用基本材質( BasicMaterial)的物體,渲染後物體的顏色,始終爲 該材質的顏色,不會因爲光照產生明暗、陰影效果。若是沒有指定材質的顏色,則顏色是隨機的,構造函數以下:
new THREE.MeshBasicMaterial(opt)
  • 其中參數opt能夠缺省,或者爲包含各屬性的值。如,爲一個黃色正方體添加一個1不透明度 (opacity)
new THREE.MeshBasicMaterial({
    color: 0xffff00,
    opacity: 0.75
});
  • 示例代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>基本材質</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();
            
            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);
            
            // 材質
            var material = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                opacity: 0.75
            });

            // 幾何體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果圖:

image

  • 下面,介紹幾個經常使用的屬性

    • visible:是否可見,默認爲true
    • side:渲染面片正面或是反面,默認爲正面THREE.FrontSide,可設置爲反面THREE.BackSide,或雙面THREE.DoubleSide
    • wireframe:是否渲染線而非面,默認爲false
    • color:十六進制RGB顏色,如紅色表示爲0xff0000
    • map:使用紋理貼圖(下面會着重講解)
  • 對於基本材質,即便改變場景中的光源,使用該材質的物體也始終爲顏色到處相同的效果。固然,這不是很具備真實感,所以,接下來咱們將介紹更爲真實的光照模型:Lambert光照模型以及Phong光照模型。

7.2 Lambert 材質

Lambert材質( MeshLambertMaterial)是符合Lambert光照模型的材質。Lambert光照模型的主要特色是隻考慮 漫反射而不考慮 鏡面反射的效果,於是對於金屬、鏡子等須要鏡面反射效果的物體就 不適應,對於其餘大部分物體的漫反射效果都是適用的。
  • 它的光照模型的公式爲:
Idiffuse = Kd * Id * cos(theta)
  • 其中,Idiffuse是漫反射光強,Kd是物體表面的漫反射屬性,Id是光強,theta是光的入射角弧度。
  • 固然,對於使用Three.js的Lambert材質,不須要了解以上公式就能夠直接使用。建立Lambert材質的構造函數以下:
new THREE.MeshLambertMaterial()
  • 示例代碼(建立一個黃色並使用光照的立方體):

    • 光照這裏不細講,後面會着重講解,這裏你們只須要知道是幹什麼用的就行
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lambert材質</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();
            
            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // 添加光照
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);

            // Lambert材質
            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00,
            });
            
            // 幾何體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果圖:

image

  • 下面,介紹幾個經常使用的屬性:

    • color是用來表現材質對散射光的反射能力,也是最經常使用來設置材質顏色的屬性。除此以外,還能夠用ambientemissive控制材質的顏色。
    • ambient表示對環境光反射能力,只有當設置了AmbientLight後,該值纔是有效的,材質對環境光的反射能力與環境光強相乘後獲得材質實際表現的顏色。
    • emissive是材質的自發光顏色,能夠用來表現光源的顏色。
  • 單獨使用紅色自發光:
var material = new THREE.MeshLambertMaterial({
    emissive: 0xff0000
})
  • 效果圖:

image

  • 若是同時使用紅色的自發光與黃色的散射光:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00,
    emissive: 0xff0000
})
  • 效果圖:

image

  • 這樣就會出現一個漸變色的效果,咱們能夠新建一個球體:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00,
    emissive: 0xff0000
});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
scene.add(sphere);
  • 效果圖:

image

7.3 Phong材質

Phong材質( MeshPhongMaterial)是符合Phong光照模型的材質。和Lambert不一樣的是,Phong模型考慮了 鏡面反射的效果,所以對於金屬、鏡面的表現尤其適合。
  • 漫反射部分和Lambert光照模型是相同的,鏡面反射模型的公式爲:
Ispecular = Ks * Is * (cos(alpha)) ^ n
  • 其中,Ispecular是鏡面反射的光強Ks是材質表面鏡面反射係數Is是光源強度alpha是反射光與視線的夾角n高光指數,越大則高光光斑越小。
  • 因爲漫反射部分與Lambert模型是一致的,所以,若是不指定鏡面反射係數,而只設定漫反射,其效果與Lambert是相同的:
new THREE.MeshPhongMaterial({
    color: 0xffff00
});
  • 完整代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Phong材質</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();
            
            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);
            
            // 材質
            var material = new THREE.MeshPhongMaterial({
                color: 0xffff00,
                //specular: 0xffff00,
                //shininess: 1000
            });
            // 幾何體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            //var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
            //scene.add(sphere);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果圖:

image

  • 下面,介紹幾個經常使用的屬性:

    • 一樣地,能夠指定emissiveambient值,這裏再也不說明。
    • 下面就specular值指定鏡面反射係數做說明。
  • 首先,咱們只使用鏡面反射(specular),將高光設爲紅色,應用於一個球體:
var material = new THREE.MeshPhongMaterial({
    specular: 0xff0000
});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
scene.add(sphere);
  • 效果圖:

image

  • 能夠經過shininess屬性控制光照模型中的n值*(高光指數,光斑),當shininess值越大時,高光的光斑越小,默認值爲30。咱們將其設置爲1000時:
var material = new THREE.MeshPhongMaterial({
    specular: 0xff0000,
    shininess: 1000
});
  • 效果圖:

image

  • 使用黃色的鏡面光,紅色的散射光:
material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    specular: 0xffff00,
    shininess: 1000
});
  • 效果圖:

image

7.4 法向材質

法向材質能夠將材質的顏色設置爲其 法向量的方向,有時候對於調試頗有幫助。
  • 法向材質的設定很簡單,不須要設置參數。構造函數以下:
new THREE.MeshNormalMaterial()

材質的顏色與照相機與該物體的角度相關,下面咱們只改變照相機位置,觀察兩個角度的顏色變化:

  • 示例代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>法向材質</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            /* 修改這裏如下的值 */ 
            camera.position.set(25, 25, 25);
            /* 修改這裏以上的值 */
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);

            // 材質
            var material = new THREE.MeshNormalMaterial();

            // 幾何體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • camera.position.set(5, 25, 25);的效果圖:

image

  • camera.position.set(25, 25, 25);的效果圖:

image

  • 咱們觀察的是一樣的三個面,可是因爲觀察的角度不一樣,物體的顏色就不一樣了。所以,在調試時,要知道物體的法向量,使用法向材質就頗有效。

7.5 材質的紋理貼圖

在此以前,咱們使用的材質都是單一顏色的,有時候,咱們卻但願使用圖像做爲材質。這時候,就須要導入圖像做爲紋理貼圖,並添加到相應的材質中。

7.5.1 單張圖像應用於長方體

  • 首先,咱們須要選擇一張長寬均爲128像素的圖像:

image

  • 將其導入到紋理texture中:
var texture = THREE.ImageUtils.loadTexture('images/01.jpg');
  • 而後,將材質的map屬性設置爲texture
var material = new THREE.MeshLambertMaterial({
    map: texture
});
  • 這樣就完成了將圖片應用於材質的基本步驟。可是因爲如今咱們還沒使用動畫,畫面只被渲染了一次,而在導入紋理以前,已經完成了此次渲染,所以看到的只是一片黑。因此,若是沒有重繪函數(將在下一章介紹),就須要在完成導入紋理的步驟後,從新繪製畫面,這是在回調函數中實現的:
var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() {
    renderer.render(scene, camera);
});
var material = new THREE.MeshLambertMaterial({
    map: texture
});
  • 注意:須要在本地服務器運行。
  • 完整代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>紋理貼圖</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 1000);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);

            // 紋理(須要重繪函數)
            var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() {
                renderer.render(scene, camera);
            });

            // 材質
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });

            // 幾何體
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            // var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
            // scene.add(sphere);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 如今,就能看到這樣的效果了:

image

  • 相似地,若是將其應用於球體,將會把整個球體應用該圖像:

image

7.5.2 六張圖像應用於長方體

有時候,咱們但願長方體的六面各類的貼圖都不一樣。所以,咱們首先準備了六張顏色各異的圖像,分別寫了數字01到06。而後,分別導入圖像到六個紋理,並設置到六個材質中:
var materials = [];
for (var i = 1; i < 7; ++i) {
    materials.push(new THREE.MeshBasicMaterial({
        map: THREE.ImageUtils.loadTexture('images/0' + i + '.jpg', {}, function() {
            renderer.render(scene, camera);
        }),
        overdraw: true
    }));
}

var cube = new THREE.Mesh(
    new THREE.CubeGeometry(2, 2, 2),
    new THREE.MeshFaceMaterial(materials));
scene.add(cube);
  • 效果爲:

image

7.5.3 棋盤

用黑白相間的圖片繪製一副棋盤

image

  • 實現代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>棋盤</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0xffffff);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-10, 10, 7.5, -7.5, 0.1, 100);
            camera.position.set(0, 0, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 1000);
            light.position.set(10, 15, 25);
            scene.add(light);

            var texture = THREE.ImageUtils.loadTexture('images/chess.png', {}, function() {
                renderer.render(scene, camera);
            });
            // texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            // texture.repeat.set(4, 4);
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });
            
            // 平面
            var plane = new THREE.Mesh(new THREE.PlaneGeometry(12, 12), material);
            scene.add(plane);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果圖:

image

但是,棋盤格是8橫8縱64個小方格組成的,那應該怎麼辦呢?

  • 首先,咱們須要指定重複方式爲兩個方向(wrapSwrapT)都重複:
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  • 而後,設置兩個方向上都重複4次,因爲咱們的圖像原本是有2行2列,因此重複4次即爲8行8列:
texture.repeat.set(4, 4);
  • 效果圖:

image

8. 網格

在學習了幾何形狀和材質以後,咱們就能使用他們來建立物體了。最經常使用的一種物體就是網格(Mesh),網格是由頂點、邊、面等組成的物體;其餘物體包括線段( Line)、骨骼( Bone)、粒子系統( ParticleSystem)等。建立物體須要指定幾何形狀和材質,其中,幾何形狀決定了物體的 頂點位置等信息,材質決定了物體的 顏色、紋理等信息。
  • 本章將介紹建立較爲經常使用的物體:網格,而後介紹如何修改物體的屬性。

8.1 建立網格

在上兩節中,咱們學習瞭如何建立幾何形狀與材質,而網格的建立很是簡單,只要把幾何形狀與材質傳入其構造函數。最經常使用的物體是網格( Mesh),它表明包含 點、線、面的幾何體,其構造函數是:
// geometry : 定義的幾何體
// material : 材質
new THREE.Mesh(geometry,material)
  • 下面,讓咱們經過一個具體的例子瞭解如何建立網格:
// 幾何體(長方體)
var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);

// 材質
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});

// 網格
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
  • 若是materialgeometry以後不會複用的話,也能夠合在一塊兒寫爲:
var mesh = new THREE.Mesh(new THREE.CubeGeometry(0.6, 1.2, 1.8), 
    new THREE.MeshLambertMaterial({
        color: 0xffff00
    })
);
scene.add(mesh);
  • 完整代碼:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>網格</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-2.5, 2.5, 1.875, -1.875, 0.1, 100);
            camera.position.set(5, 5, 20);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照 
            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(20, 10, 5);
            scene.add(light);

            // 材質
            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00
            });

            // 幾何體
            var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);

            // 網格
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);

            // render
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果圖:

image

8.2 修改屬性

8.2.1 材質

除了在構造函數中指定材質,在網格被建立後,也能對材質進行修改:
  • 示例代碼:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});
var geometry = new THREE.CubeGeometry(1, 2, 3);
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// 從新賦值
mesh.material = new THREE.MeshLambertMaterial({
    color: 0xff0000
});
  • 最終會顯示紅色,緣由很簡單,在js語言預解析中,下面材質從新賦值後,就覆蓋了上面定義的材質。
  • 效果圖

image

8.2.2 位置、縮放、旋轉

位置、縮放、旋轉是物體三個經常使用屬性。因爲 THREE.Mesh基礎自 THREE.Object3D,所以包含 scale、rotation、position三個屬性。它們都是 THREE.Vector3實例,所以修改其值的方法是相同的,這裏以 位置爲例。
  • THREE.Vector3x、y、z三個屬性,若是隻設置其中一個屬性,則能夠用如下方法:
mesh.position.z = 1;
  • 若是須要同時設置多個屬性,可使用如下兩種方法:
mesh.position.set(1.5, -0.5, 0);
mesh.position = new THREE.Vector3(1.5, -0.5, 0);
  • 示例代碼(修改位置):
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>修改位置</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 場景
            var scene = new THREE.Scene();

            // 相機
            var camera = new THREE.OrthographicCamera(-2.5, 2.5, 1.875, -1.875, 0.1, 100);
            camera.position.set(5, 5, 10);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00
            });
            var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);

            // 修改位置屬性
            mesh.position.set(1, 0, 0);
            // mesh.position = new THREE.Vector3(1.5, -0.5, 0);
            // mesh.position.x = 1;

            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(20, 10, 5);
            scene.add(light);

            // 座標軸
            drawAxes(scene);

            // 渲染
            renderer.render(scene, camera);


            function drawAxes(scene) {
                // x-axis
                var xGeo = new THREE.Geometry();
                xGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                xGeo.vertices.push(new THREE.Vector3(3, 0, 0));
                var xMat = new THREE.LineBasicMaterial({
                    color: 0xff0000
                });
                var xAxis = new THREE.Line(xGeo, xMat);
                scene.add(xAxis);

                // y-axis
                var yGeo = new THREE.Geometry();
                yGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                yGeo.vertices.push(new THREE.Vector3(0, 3, 0));
                var yMat = new THREE.LineBasicMaterial({
                    color: 0x00ff00
                });
                var yAxis = new THREE.Line(yGeo, yMat);
                scene.add(yAxis);

                // z-axis
                var zGeo = new THREE.Geometry();
                zGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                zGeo.vertices.push(new THREE.Vector3(0, 0, 3));
                var zMat = new THREE.LineBasicMaterial({
                    color: 0x00ccff
                });
                var zAxis = new THREE.Line(zGeo, zMat);
                scene.add(zAxis);
            }
        }
    </script>
</body>

</html>
  • 效果圖

image

  • 縮放對應的屬性是scale旋轉對應的屬性是rotation,具體方法與上例相同,分別表示沿x、y、z三軸縮放或旋轉。
相關文章
相關標籤/搜索