:)
簡介
在三維空間中的物體是由點(diǎn)、線、面組成的
- 點(diǎn): 三維空間中的一個點(diǎn)(包含x , y ,z)
- 線:兩個點(diǎn)就能確定一條直線(包含起點(diǎn)和終點(diǎn))晓猛,多個點(diǎn)可以繪制一條折線
- 面:三個點(diǎn)就可以確定一個面(暫時(shí)理解成WebGL里面僅僅支持 三角形的繪制)
- 三維物體:多個面組合起來就可以構(gòu)成一個三維物體
不管是點(diǎn) 访敌、線還是面,里面的坐標(biāo)點(diǎn)都叫頂點(diǎn)着倾。可以給不同的頂點(diǎn)設(shè)置不同的顏色燕少,這個過程叫著色(看不懂的話有個概念就行卡者,頂點(diǎn) + 顏色 = 三維物體)
點(diǎn)
- 定義點(diǎn)的位置(x,y客们,z)崇决,ThreeJs中使用 THREE.Vector3 來存儲三維坐標(biāo)信息
// 定義了三個坐標(biāo)信息 (0, 0, 0) (1, 1, 0) (2, 2, 0)
var p1 = new THREE.Vector3(0,0,0);
var p2 = new THREE.Vector3(1,1,0);
var p3 = new THREE.Vector3(2,2,0);
- 定義一個存儲這些點(diǎn)的容器(可以簡單理解成GPU為了提高繪制的效率,會一次性的讀取所有的點(diǎn)底挫,所以需要一個容器來存儲所有的點(diǎn)信息)恒傻,ThreeJs里面使用 THREE.Geometry 來存儲點(diǎn)的信息
// 定義存儲點(diǎn)的容器
var pointsG = new THREE.Geometry();
pointsG.vertices.push(p1, p2, p3);
- 定義點(diǎn)的顯示樣式(不懂不要緊,樣式后面會詳解建邓。簡單理解就是點(diǎn)的顏色盈厘,大小)
// 定義點(diǎn)的顏色是紅色 大小是0.1
var pointsM = new THREE.PointsMaterial({
color: 0xff0000, size: 0.1
});
- 繪制點(diǎn)ThreeJs中 THREE.Points 這個類會將定義好的頂點(diǎn)涝缝,使用點(diǎn)的方式繪制出來
// 使用點(diǎn)的方式繪制定義好的頂點(diǎn) 并添加到場景中
var points = new THREE.Points(pointsG, pointsM);
scene.add(points);
這里的points可以指定顯示在場景的位置扑庞,而points里面定義的頂點(diǎn)是相對于場景位置的點(diǎn)
- 點(diǎn)繪制小結(jié)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="three.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 定義了三個坐標(biāo)信息 (0, 0, 0) (1, 1, 0) (2, 2, 0)
var p1 = new THREE.Vector3(0,0,0);
var p2 = new THREE.Vector3(1,1,0);
var p3 = new THREE.Vector3(2,2,0);
// 定義存儲點(diǎn)的容器
var pointsG = new THREE.Geometry();
pointsG.vertices.push(p1, p2, p3);
// 定義點(diǎn)的顏色是紅色 大小是0.1
var pointsM = new THREE.PointsMaterial({
color: 0xff0000, size: 0.1
});
// 使用點(diǎn)的方式繪制定義好的頂點(diǎn) 并添加到場景中
var points = new THREE.Points(pointsG, pointsM);
scene.add(points);
camera.position.set(5, 5, 5);
camera.lookAt(new THREE.Vector3(0,0,0));
document.getElementById("container").appendChild(renderer.domElement);
function run() {
renderer.render(scene, camera);
requestAnimationFrame(run);
}
run();
</script>
</html>
線
- 至少兩個頂點(diǎn)構(gòu)成了一條線譬重。線的繪制流程和點(diǎn)類似,定義頂點(diǎn)罐氨,設(shè)置樣式臀规,添加到場景
- 定義線經(jīng)過的頂點(diǎn)
// 定義線經(jīng)過的頂點(diǎn)
var p1 = new THREE.Vector3(1,0,0);
var p2 = new THREE.Vector3(1,1,0);
var p3 = new THREE.Vector3(2,2,0);
var p4 = new THREE.Vector3(2,1,0);
- 定義存儲點(diǎn)的容器
// 定義存儲點(diǎn)的容器
var pointsG = new THREE.Geometry();
pointsG.vertices.push(p1, p2, p3, p4);
- 設(shè)置線的樣式(樣式相關(guān)后面專門講)
// 設(shè)置線的樣式
var lineM = new THREE.LineBasicMaterial({color: 0xff0000});
- 使用THREE.Line將點(diǎn)用線的方式連接起來
// 折線
var line = new THREE.Line(pointsG, lineM);
scene.add(line);
- 使用THREE.LineLoop繪制封閉的線
// 封閉的線
var line = new THREE.LineLoop(pointsG, lineM);
scene.add(line);
- 使用THREE.LineSegments繪制線段(會將點(diǎn)進(jìn)行兩輛組合,就會生成多個線段)
// 繪制線段
var line = new THREE.LineSegments(pointsG, lineM);
scene.add(line);
線的繪制模式有三種栅隐,折線(Line)塔嬉、密封的線(LineLoop)、線段(兩兩一組的線段租悄,LineSegments)
線的繪制代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="three.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 定義線經(jīng)過的頂點(diǎn)
var p1 = new THREE.Vector3(1,0,0);
var p2 = new THREE.Vector3(1,1,0);
var p3 = new THREE.Vector3(2,2,0);
var p4 = new THREE.Vector3(2,1,0);
// 定義存儲點(diǎn)的容器
var pointsG = new THREE.Geometry();
pointsG.vertices.push(p1, p2, p3, p4);
// 設(shè)置線的樣式
var lineM = new THREE.LineBasicMaterial({color: 0xff0000});
// 繪制線段
var line = new THREE.LineSegments(pointsG, lineM);
scene.add(line);
camera.position.set(5, 5, 5);
camera.lookAt(new THREE.Vector3(0,0,0));
document.getElementById("container").appendChild(renderer.domElement);
function run() {
renderer.render(scene, camera);
requestAnimationFrame(run);
}
run();
</script>
</html>
面
- 繪制平面的套路和繪制線和點(diǎn)的套路有一些區(qū)別
- 定義這個平面上的頂點(diǎn)
// 定義平面上的頂點(diǎn)
var vertices = [
new THREE.Vector3(0,0,0),
new THREE.Vector3(1,2,0),
new THREE.Vector3(2,2,0),
];
- 處理存放頂點(diǎn)的容器
// 定義存儲點(diǎn)的容器
var geo = new THREE.Geometry();
geo.vertices = vertices;
這里我們雖然定義了頂點(diǎn)谨究,但是還沒有告訴ThreeJs怎么通過這些頂點(diǎn)來構(gòu)成平面。這里可能有些疑惑泣棋,我都已經(jīng)定義好了平面上的頂點(diǎn)了胶哲,為啥不能直接根據(jù)頂點(diǎn)生成平面?原因是在于三維空間中的物體是由很多很多平面構(gòu)成的潭辈,平面于平面之間的頂點(diǎn)會有重合鸯屿,如果直接用頂點(diǎn)的話會有很多重復(fù)的頂點(diǎn)定義。
- 定義怎么通過頂點(diǎn)構(gòu)成平面把敢,ThreeJs里面通過 THREE.Face3 這個類來定義平面
// 定義平面
geo.faces = [
new THREE.Face3(2,1,0) // 這里的 2 , 1, 0 指的是vertices定義的頂點(diǎn)的下標(biāo)
];
上面定義了一個平面寄摆,THREE.Face3(2,1,0) 這個里面的 2 指的是 vertices 里面下標(biāo)為2的頂點(diǎn),1 指的是下標(biāo)為1的頂點(diǎn)修赞,0 指的是下標(biāo)為0的頂點(diǎn)婶恼。 2,1柏副,0 的順序也是有說法的(GPU為了提高渲染效率勾邦,默認(rèn)僅僅渲染逆時(shí)針方向的平面,如果你寫成了 0割择,1检痰,2 就可能渲染不出來)
- 設(shè)置平面的樣式(具體什么意思后面專門講)
// 設(shè)置平面的樣式
var meshM = new THREE.MeshBasicMaterial({color: 0xffff00});
- 生成平面,使用的是ThreeJs里面的 THREE.Mesh
// 繪制平面
var mesh = new THREE.Mesh(geo, meshM);
- 平面繪制代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="three.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 定義平面上的頂點(diǎn)
var vertices = [
new THREE.Vector3(0,0,0),
new THREE.Vector3(1,2,0),
new THREE.Vector3(2,2,0),
];
// 定義存儲點(diǎn)的容器
var geo = new THREE.Geometry();
geo.vertices = vertices;
// 定義平面
geo.faces = [
// 定義了一個平面
new THREE.Face3(2,1,0) // 這里的 2 , 1, 0 指的是vertices定義的頂點(diǎn)的下標(biāo)
];
// 設(shè)置平面的樣式
var meshM = new THREE.MeshBasicMaterial({color: 0xff0000});
// 繪制平面
var mesh = new THREE.Mesh(geo, meshM);
scene.add(mesh);
camera.position.set(5, 5, 5);
camera.lookAt(new THREE.Vector3(0,0,0));
document.getElementById("container").appendChild(renderer.domElement);
function run() {
renderer.render(scene, camera);
requestAnimationFrame(run);
}
run();
</script>
</html>
三維物體
- 多個平面組合起來就是三維物體锨推,所以套路就是定義很多頂點(diǎn),按照頂點(diǎn)組成很多平面(注意:只能是三角形哈公壤,所以要渲染一個矩形的話就需要兩個三角形拼接起來)换可。
- 這里就直接給代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="three.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 立方體的8個頂點(diǎn)
var vertices = [
new THREE.Vector3(1, 1, 1), //v0
new THREE.Vector3(-1, 1, 1), //v1
new THREE.Vector3(-1, -1, 1), //v2
new THREE.Vector3(1, -1, 1), //v3
new THREE.Vector3(1, -1, -1), //v4
new THREE.Vector3(1, 1, -1), //v5
new THREE.Vector3(-1, 1, -1), //v6
new THREE.Vector3(-1, -1, -1) //v7
];
// 定義存儲點(diǎn)的容器
var geo = new THREE.Geometry();
geo.vertices = vertices;
// 定義立方體的各個平面,
// 立方體的每個面都是一個正方形厦幅,正方形需要兩個三角形沾鳄,所以定義了12個Face3
geo.faces = [
// 定義了一個平面
new THREE.Face3(0,1,2),
new THREE.Face3(0,2,3),
new THREE.Face3(0,3,4),
new THREE.Face3(0,4,5),
new THREE.Face3(1,6,7),
new THREE.Face3(1,7,2),
new THREE.Face3(6,5,4),
new THREE.Face3(6,4,7),
new THREE.Face3(5,6,1),
new THREE.Face3(5,1,0),
new THREE.Face3(3,2,7),
new THREE.Face3(3,7,4)
];
// 設(shè)置平面的樣式
var meshM = new THREE.MeshBasicMaterial({color: 0xff0000});
// 繪制平面
var mesh = new THREE.Mesh(geo, meshM);
scene.add(mesh);
camera.position.set(5, 5, 5);
camera.lookAt(new THREE.Vector3(0,0,0));
document.getElementById("container").appendChild(renderer.domElement);
function run() {
renderer.render(scene, camera);
requestAnimationFrame(run);
}
run();
</script>
</html>
threejs - 1 - 介紹&入門
threejs - 2 - 相機(jī)
threejs - 3 - 場景刷新
threejs - 4 - 物體
[threejs - 5 - 材質(zhì)]
[threejs - 6 - 燈光]
[threejs - 7 - 相機(jī)進(jìn)階]
[threejs - 8 - 物體進(jìn)階]
[threejs - 9 - 粒子系統(tǒng)]
[threejs - 10 - 模型加載]
[threejs - 11 - GLSL]
[threejs - 12 - 著色器]
End.