WebGL是在瀏覽器中實現三維效果的一套規範
什麼是threejs,很簡單,你將它理解成three+js
就能夠了。three表示3D的意思
,js表示javascript的意思
。那麼合起來,three.js
就是使用javascript
來寫3D程序
的意思。
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
渲染器
決定了渲染的結果
應該畫在頁面的什麼元素上面
,而且以怎樣的方式來繪製
。渲染器將會和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);
在Three.js中添加物體
都是添加到場景
中的,所以它至關於一個大容器。通常說,場景裏沒有很複雜的操做,只要new一個對象就能夠了,而後將物體添加到場景中便可。
var scene = new THREE.Scene();
在介紹照相機以前,咱們先來介紹一下座標系。
這裏咱們定義一個
透視相機
(相機也須要添加到場景中):
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000); // 設置相機的位置 camera.position.set(0,0,5); // 將相機添加到場景中 scene.add(camera);
這裏咱們先介紹一個長方體,建立一個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(); 表示調用一個幾何體前端
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; });
必定不要忘了,將物體添加到場景
在定義了場景中的物體,設置好的照相機以後,渲染器就知道如何渲染出二維的結果了。這時候,咱們只須要調用渲染器的渲染函數,就能使其渲染一次了。
renderer.render(scene, camera);
<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>
canvas元素的默認寬高爲300/150python
下面介紹下Three.js官網文檔中的一些重要的對象,在你須要尋求幫助時,就可以知道關鍵詞是什麼。
Cameras(照相機,控制投影方式)git
Core(核心對象)程序員
Lights(光照)github
Loaders(加載器,用來加載特定文件)web
Materials(材質,控制物體的顏色、紋理等)算法
Math(和數學相關的對象)
Objects(物體)
Renderers(渲染器,能夠渲染到不一樣對象上)
Renderers / Renderables
Scenes(場景)
Textures(紋理)
Extras
Extras / Animation
Extras / Cameras
Extras / Core
Extras / Geometries(幾何形狀)
Extras / Helpers
Extras / Objects
Extras / Renderers / Plugins
Extras / Shaders
咱們看到,Three.js功能是十分豐富的,一時間想所有掌握有些困難。在接下來的章節中,咱們將會先詳細介紹照相機、幾何形狀、材質、物體等入門級知識;而後介紹使用動畫、模型導入、加入光照等功能;最後,對於學有餘力的讀者,咱們將介紹着色器,用於更高級的圖形渲染。
本章將介紹照相機的概念,以及如何使用Three.js設置相應的參數。
在圖形學中,照相機可沒有生活中的照相機那麼簡單
投影方式
的不一樣,照相機又分爲正交投影照相機
與透視投影照相機
。咱們須要爲本身的程序選擇合適的照相機。這二者分別是什麼,以及二者有何差別,咱們將在下節中做介紹。舉個簡單的例子來講明正交投影與透視投影照相機的區別。使用透視投影照相
機得到的結果是相似人眼在真實世界中看到的有「近大遠小」
的效果(以下圖中的(a));而使用正交投影照相機
得到的結果就像咱們在數學幾何學課上老師教咱們畫的效果,對於三維空間內平行的線
,投影到二維空間中也必定是平行的
(以下圖中的(b))。
通常說來,對於製圖、建模軟
一般使正交投影
,這樣不會由於投影而改變物體比例;而對於其餘大多數應用
,一般使用 透視投影
,由於這更接近人眼的觀察效果。固然,照相機的選擇並無對錯之分,你能夠更具應用的特性,選擇一個效果更佳的照相機。
正交投影照相機(
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的值設置得較大
,具體值視場景中物體的位置等決定。
下面咱們經過一個具體的例子來了解正交投影照相機的設置
基本設置
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10); camera.poaition.set(0,0,5); scene.add(camera);
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)
。
透視投影照相機(
Perspective Camera
)
THREE.PerspectiveCamera(fov, aspect, near, far)
讓咱們經過一張透視照相機投影的圖來了解這些參數。
灰色
的部分是視景體
,是可能被渲染
的物體所在的區域。fov
是視景體豎直方向上
的張角
(是角度制而非弧度制),如側視圖所示。aspect
等於width / height
,是照相機水平方向和豎直方向長度的比值
,一般設爲Canvas的橫縱比例
。near和far
分別是照相機到視景體
最近、最遠
的距離,均爲正值
,且far應大於near
。下面咱們經過一個例子來學習透視投影照相機
基本設置
800px
,寬600px
,因此aspect
設爲800 / 600
:var camera = new THREE.PerspectiveCamera(45, 800 / 600, 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);
所有的12條邊
,並且有近大遠小
的效果,這也就是與正交投影的區別。豎直張角
fov
的改變對渲染效果的影響。咱們將原來的45改成60
:var camera = new THREE.PerspectiveCamera(60, 800 / 600, 1, 10); camera.position.set(0, 0, 5); scene.add(camera);
豎直張角
設置得更大
時,視景體變大了
,於是正方體
相對於整個視景體
的大小就變小
了,看起來正方形就顯得變小了。
改變fov
並不會
引起畫面橫豎比例
的變化,而改變aspect
則會
改變橫豎比例。在計算機世界裏,3D世界由點組成,兩個點能組成一條直線,三個不在一條直線上的點,就能組成一個三角面,無數的三角面
就能組成各類各樣的物體
,以下圖:
網絡模型
叫作Mesh模型
。給物體貼上皮膚
,或者專業點就叫作紋理
,那麼這個物體就活靈活現了。最後無數的物體就組成了咱們的3D世界。在三維空間中的某一個點能夠用一個座標點來表示。一個座標點由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; };
Vector3
是定義在THREE
下面的一個類
。之後要用Vector3
,就必須要加THREE前綴
。固然Three.js的設計者,也能夠不加THREE這個前綴,可是他們預見到,Three.js引擎中會有不少類型,最好給這些類型加一個前綴,以避免與開發者的代碼產生衝突。函數
。這個函數有3個參數
,分別表明x座標
,y座標
和z座標
的份量。函數體內的代碼將他們分別賦值給成員變量x,y,z
。看看上面的代碼,中間使用了一個「||」(或)運算符
,就是當x=null或者undefine
時,this.x
的值應該取0
。在3D世界中點
能夠用THREE.Vector3D
來表示。
var point1 = new THREE.Vecotr3(4,8,9);
set
方法,代碼以下:var point1 = new THREE.Vector3(); point1.set(4,8,9);
兩個不重合的點可以決定一條直線。在three.js中,也能夠經過定義兩個點,來畫一條直線。
vertices變量
,能夠用來存放點
var geometry = new THREE.Geometry(); // 幾何體裏面有個vertices變量,能夠用來存放點
THREE.LineBasicMaterial
類型來定義,它接受一個集合做爲參數
,其原型以下:THREE.LineBasicMaterial(parameters);
parameters
是定義材質外觀的對象,它包含多個屬性來定義材質,這些屬性是:
顏色
,用16進製表示,默認都是白色寬度
,默認是1個單位寬度兩端的外
觀,默認是圓角端點
,當線條較粗的時候才能看到效果鏈接點處的外觀
,默認是「round」,表示圓角。線條材質
是否使用頂點顏色
,這是一個boolean值。意思是,線條各部分的顏色會根據頂點的顏色來進行插值。頂點顏色
vertexColors: THREE.VertexColors
,就是線條的顏色
會根據頂點
來計算。var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
WebGLRender
渲染方式是不之持繪製線寬的,要想支持,須要將渲染方式設置爲CanvasRenderer
var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 );
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);
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>
在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);
push方法
,是由於geometry.vertices
是一個數組
。這樣geometry中就有了2個點了。THREE.LineBasicMaterial
。var material = new THREE.LineBasicMaterial();
THREE.Line
繪製了一條線:var line = new THREE.Line( geometry, material, THREE.LinePieces );
咱們要畫一個網格的座標,那麼咱們就應該找到線的點。把網格虛擬成正方形,在正方形邊界上找到幾個等分點,用這些點兩兩鏈接,就可以畫出整個網格來。
// 在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 ));
二、算法
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>
在建立物體時,須要傳入兩個參數,一個是幾何形狀(Geometry)
,另外一個是材質(Material)
,這一章將着重介紹幾何形狀的建立,第6章介紹材質,第7章介紹如何使用二者建立網格。
頂點信息
。WebGL須要程序員指定每一個頂點的位置,而在Three.js中,能夠經過指定一些特徵
來建立幾何形狀,例如使用半徑
建立一個球體
,從而省去程序員一個個指定頂點的工做量。手動定義
頂點位置
和面片信息
組成幾何形狀。
雖然這形狀的名字叫作立方體(
CubeGeometry
),但實際上是長方體,也就是長寬高能夠設置不一樣的值:
new THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
width
是x方向
上的長度;height
是y方向
上的長度;depth
是z方向上
的長度;後三個參數分別是在三個方向上的分段數
,如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);
默認位置
是原點
,對於立方體而言,是其幾何中心在原點的位置。分段
THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
,的後三個參數,爲這個長方體分段:// x軸分兩段 y軸分兩段 z軸分三段 new THREE.CubeGeometry(1, 2, 3, 2, 2, 3)
六個面
進行分段,而不是對立方體的體素分段,所以在立方體的中間是不分段
的,只有六個側面
被分段。
這裏的平面(
PlaneGeometry
)實際上是一個長方形,而並不是是數學意義上無限大的平面:
new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
width
是x方向
上的長度;height
是y方向
上的長度;後兩個參數一樣表示分段
。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);
x軸和z軸
所在的平面內,能夠經過物體的旋轉
來實現,具體的作法將在下面章節介紹到。
球體(
SphereGeometry
)的構造函數是:
new THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
radius
是半徑
;segmentsWidth
表示經度上的切片數
;segmentsHeight
表示緯度上的切片數
;phiStart
表示經度開始的弧度
;phiLength
表示經度跨過的弧度
;thetaStart
表示緯度開始的弧度
;thetaLength
表示緯度跨過的弧度
。分段
segmentsWidth
和segmentsHeight
。使用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);
new THREE.SphereGeometry(2, 8, 16)
的效果如圖:
new THREE.SphereGeometry(3, 18, 12)
的效果如圖:
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);
SegmentsWidth
爲8
意味着對於經度從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);
經度緯度
都改變了起始位置和跨度
的例子: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);
圓形(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);
圓柱體(
CylinderGeometry
)的構造函數是:
new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
radiusTop
與radiusBottom
分別是頂面和底面的半徑
,由此可知,當這兩個參數設置爲不一樣的值時,實際上建立的是一個圓臺;height
是圓柱體的高度
;radiusSegments
與heightSegments
可類比球體中的分段
,一個表示底面、頂面的分段,另外一個表示環面的分段;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);
圓臺
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);
無底面、頂面
openEnded
爲true
的時候,將無底面、頂面。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);
正四面體(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);
正八面體
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);
正二十面體
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);
圓環面(
TorusGeometry
)就是甜甜圈的形狀,其構造函數是:
new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)
radius
是圓環半徑;tube
是管道半徑;radialSegments
與tubularSegments
分別是兩個分段數,詳見上圖;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);
精細圓環面
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);
部分圓環面
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);
若是說圓環面是甜甜圈,那麼圓環結(
TorusKnotGeometry
)就是打告終的甜甜圈,其構造參數爲:
new THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments, p, q, heightScale)
p
和q
是控制其樣式
的參數,通常能夠缺省,若是須要詳細瞭解,請學習圓環結的相關知識;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);
文字形狀(
TextGeometry
)能夠用來建立三維的文字形狀。
使用文字前,須要下載和引用額外的字體庫。字體庫在
three.js Github master/examples/fonts目錄下,下載裏面的
json
文件,放在你的目錄下,而後加載。
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。webstorm
編輯器,由於它打開html文件時,就是以本地服務器的方式打開的。或者在cmd命令行中輸入live-server
,但須要配置,具體方法請點這裏。建立文字形狀的流程和以前介紹的基本幾何形狀是相似的,其構造函數是:
new THREE.TextGeometry(text, parameters)
其中,text
是要顯示的文字字符串,parameters
是如下參數組成的對象:
size
:字號大小,通常爲大寫字母的高度height
:文字的厚度curveSegments
:弧線分段數,使得文字的曲線更加光滑font
:字體,默認是'helvetiker'
,需對應引用的字體文件weight
:值爲'normal'
或'bold'
,表示是否加粗style
:值爲'normal'
或'italics'
,表示是否斜體bevelEnabled
:布爾值,是否使用倒角,意爲在邊緣處斜切bevelThickness
:倒角厚度bevelSize
:倒角寬度
建立一個三維文字
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>
// 將材質改成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);
對於Three.js沒有提供的形狀,能夠經過自定義形狀來建立。
Geometry
類,它是其餘如CubeGeometry、SphereGeometry等幾何形狀的父類,其構造函數是:new THREE.Geometry()
咱們以建立一個梯臺爲例,首先,初始化一個幾何形狀,而後設置頂點位置以及頂點鏈接狀況。
geometry
建立點的時候都是push
到數組vertices
裏面的Face3
的方法將3
點連成一個三角面
// 初始化幾何形狀 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));
總結:
new THREE.Vector3(-1, 2, -1)
建立一個矢量
,做爲頂點位置追加到geometry.vertices
數組中。new THREE.Face3(0, 1, 3)
建立一個三個頂點組成的面片
,追加到geometry.faces
數組中。三個參數分別是四個頂點在geometry.vertices
中的序號。
材質(
material
),是獨立於物體頂點信息以外的與渲染效果相關的屬性。經過設置材質能夠改變物體顏色、紋理貼圖、光照模式等。
基本材質
、兩種基於光照模型材質
、法向量做爲材質
、 圖像做爲材質
。使用基本材質(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>
下面,介紹幾個經常使用的屬性
visible
:是否可見,默認爲trueside
:渲染面片正面或是反面,默認爲正面THREE.FrontSide
,可設置爲反面THREE.BackSide
,或雙面THREE.DoubleSide
wireframe
:是否渲染線而非面,默認爲false
color
:十六進制RGB顏色,如紅色表示爲0xff0000map
:使用紋理貼圖(下面會着重講解)基本材質
,即便改變場景中的光源,使用該材質的物體也始終爲顏色到處相同的效果。固然,這不是很具備真實感,所以,接下來咱們將介紹更爲真實的光照模型:Lambert光照模型以及Phong光照模型。Lambert材質(MeshLambertMaterial
)是符合Lambert光照模型的材質。Lambert光照模型的主要特色是隻考慮漫反射
而不考慮鏡面反射
的效果,於是對於金屬、鏡子等須要鏡面反射效果的物體就不適應
,對於其餘大部分物體的漫反射效果都是適用的。
Idiffuse = Kd * Id * cos(theta)
Idiffuse
是漫反射光強,Kd
是物體表面的漫反射屬性,Id
是光強,theta
是光的入射角弧度。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>
下面,介紹幾個經常使用的屬性:
color
是用來表現材質對散射光的反射能力,也是最經常使用來設置材質顏色的屬性。除此以外,還能夠用ambient
和emissive
控制材質的顏色。ambient
表示對環境光
的反射能力
,只有當設置了AmbientLight
後,該值纔是有效的,材質對環境光的反射能力與環境光強相乘後獲得材質實際表現的顏色。emissive
是材質的自發光
顏色,能夠用來表現光源的顏色。var material = new THREE.MeshLambertMaterial({ emissive: 0xff0000 })
var material = new THREE.MeshLambertMaterial({ color: 0xffff00, emissive: 0xff0000 })
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);
Phong材質(MeshPhongMaterial
)是符合Phong光照模型的材質。和Lambert不一樣的是,Phong模型考慮了鏡面反射
的效果,所以對於金屬、鏡面的表現尤其適合。
Ispecular = Ks * Is * (cos(alpha)) ^ n
Ispecular
是鏡面反射的光強
,Ks
是材質表面鏡面反射係數
,Is
是光源強度
,alpha
是反射光與視線的夾角
,n
是高光指數
,越大則高光光斑越小。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>
下面,介紹幾個經常使用的屬性:
emissive
和ambient
值,這裏再也不說明。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);
shininess
屬性控制光照模型中的n值*(高光指數,光斑)
,當shininess
值越大時,高光的光斑越小
,默認值爲30
。咱們將其設置爲1000
時:var material = new THREE.MeshPhongMaterial({ specular: 0xff0000, shininess: 1000 });
material = new THREE.MeshPhongMaterial({ color: 0xff0000, specular: 0xffff00, shininess: 1000 });
法向材質能夠將材質的顏色設置爲其
法向量的方向
,有時候對於調試頗有幫助。
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);
的效果圖:
camera.position.set(25, 25, 25);
的效果圖:
在此以前,咱們使用的材質都是單一顏色的,有時候,咱們卻但願使用圖像做爲材質。這時候,就須要導入圖像做爲紋理貼圖,並添加到相應的材質中。
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>
有時候,咱們但願長方體的六面各類的貼圖都不一樣。所以,咱們首先準備了六張顏色各異的圖像,分別寫了數字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);
用黑白相間的圖片繪製一副棋盤
<!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>
但是,棋盤格是8橫8縱64
個小方格組成的,那應該怎麼辦呢?
wrapS
和wrapT
)都重複:texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(4, 4);
在學習了幾何形狀和材質以後,咱們就能使用他們來建立物體了。最經常使用的一種物體就是網格(Mesh),網格是由頂點、邊、面等組成的物體;其餘物體包括線段(Line
)、骨骼(Bone
)、粒子系統(ParticleSystem
)等。建立物體須要指定幾何形狀和材質,其中,幾何形狀決定了物體的頂點位置
等信息,材質決定了物體的顏色、紋理
等信息。
在上兩節中,咱們學習瞭如何建立幾何形狀與材質,而網格的建立很是簡單,只要把幾何形狀與材質傳入其構造函數。最經常使用的物體是網格(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);
material
和geometry
以後不會複用
的話,也能夠合在一塊兒寫爲: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>
除了在構造函數中指定材質,在網格被建立後,也能對材質進行修改:
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 });
位置、縮放、旋轉是物體三個經常使用屬性。因爲THREE.Mesh
基礎自THREE.Object3D
,所以包含scale、rotation、position
三個屬性。它們都是THREE.Vector3
實例,所以修改其值的方法是相同的,這裏以位置
爲例。
THREE.Vector3
有x、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>
縮放
對應的屬性是scale
,旋轉
對應的屬性是rotation
,具體方法與上例相同,分別表示沿x、y、z
三軸縮放或旋轉。