1卡骂、簡(jiǎn)介
WebGL 是在瀏覽器中實(shí)現(xiàn)三維效果的一套規(guī)范钞楼,而 Three.js 可以看成是瀏覽器對(duì) WebGL 規(guī)范實(shí)現(xiàn)的一套封裝, 能夠讓 Web 開(kāi)發(fā)者使用 JavaScript 語(yǔ)言直接和顯卡(GPU)進(jìn)行通信振湾。其中得 GLSL 是GPU 部分對(duì)應(yīng)的編程語(yǔ)言暇务,可以用 GLSL 編寫(xiě)著色器程序,并配合 JavaScript 共同實(shí)現(xiàn) 3D 效果拿撩。一個(gè)簡(jiǎn)單的 Three.js 程序包含以下幾個(gè)部分:
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="http://wow.techbrood.com/libs/three.r73.js"></script>
<script>
// 1衣厘、建立場(chǎng)景
var scene = new THREE.Scene();
// 2、建立相機(jī)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
// 3压恒、建立渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// 4影暴、建立物體
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
// 5、開(kāi)始繪制
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
2探赫、概念介紹
- 場(chǎng)景
在 Threejs 中場(chǎng)景就只有一種型宙,用THREE.Scene來(lái)表示,要構(gòu)件一個(gè)場(chǎng)景也很簡(jiǎn)單伦吠,只要new一個(gè)對(duì)象就可以了妆兑,代碼如下:
var scene = new THREE.Scene();
場(chǎng)景是所有物體的容器,如果要顯示一個(gè)蘋果毛仪,就需要將蘋果對(duì)象加入場(chǎng)景中搁嗓。
- 相機(jī)
相機(jī)決定了場(chǎng)景中哪個(gè)角度的景色會(huì)顯示出來(lái),在 Threejs 中有多種相機(jī)箱靴,這里介紹兩種腺逛,它們是:
透視相機(jī)(THREE.PerspectiveCamera)和正投影相機(jī)(THREE.OrthographicCamera),透視相機(jī)跟人眼差不多刨晴,有近大遠(yuǎn)小的效果屉来,而正投影相機(jī)則沒(méi)有這個(gè)效果路翻,所有東西顯示都是一樣大
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
- 渲染器
渲染器決定了渲染的結(jié)果應(yīng)該畫(huà)在頁(yè)面的什么元素上面,并且以怎樣的方式來(lái)繪制茄靠。ThreeJS 框架提供了好幾種渲染器對(duì)象茂契,分別使用不同的底層技術(shù)實(shí)現(xiàn),比如:
WebGLRenderer使用 WebGL 技術(shù)慨绳;CanvasRenderer使用 Canvas 2D 技術(shù)掉冶;CSS2DRenderer和CSS3DRenderer則是使用 CSS 技術(shù);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
- 物體 Mesh
Mesh 好比一個(gè)包裝工脐雪,它將『可視化的材質(zhì)』粘合在一個(gè)『數(shù)學(xué)世界里的幾何體』上厌小,形成一個(gè)『可添加到場(chǎng)景的對(duì)象』。
當(dāng)然战秋,創(chuàng)建的材質(zhì)和幾何體可以多次使用(若需要)璧亚。而且,包裝工不止一種脂信,還有 Points(點(diǎn)集)癣蟋、Line(線/虛線) 等,比如添加一個(gè)幾何體到場(chǎng)景中:
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
CubeGeometry 表示一個(gè)幾何體
幾何體 Geometry
目前 Three.js 一共提供了 22 個(gè) Geometry狰闪,詳情參見(jiàn)https://aotu.io/notes/2017/08/28/getting-started-with-threejs/index.html點(diǎn) & 線
創(chuàng)建一個(gè)點(diǎn):
var point1 = new THREE.Vecotr3(4,8,9);
// or
var point1 = new THREE.Vector3();
point1.set(4,8,9)
創(chuàng)建一條線:線由點(diǎn)組成(準(zhǔn)確來(lái)說(shuō)由點(diǎn)疯搅,材質(zhì)和顏色組成),所以先創(chuàng)建點(diǎn)埋泵,再組合點(diǎn)(通過(guò)Geometry組織點(diǎn))幔欧,Threejs 中沒(méi)有提供單獨(dú)畫(huà)點(diǎn)的函數(shù),它必須被放到一個(gè)THREE.Geometry形狀中
// 方式 1
var geometry = new THREE.Geometry();
var material = new THREE.LineBasicMaterial( { vertexColors: true } );
var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 );
// 線的材質(zhì)可以由2點(diǎn)的顏色決定
var p1 = new THREE.Vector3( -100, 0, 100 );
var p2 = new THREE.Vector3( 100, 0, -100 );
// vertices 保存點(diǎn)丽声,colors 保存對(duì)應(yīng)點(diǎn)的顏色
geometry.vertices.push(p1);
geometry.vertices.push(p2);
geometry.colors.push( color1, color2 );
var line = new THREE.Line( geometry, material, THREE.LinePieces );
// 方式 2
var geometry = new THREE.Geometry();
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 );
}
操作線的某一維坐標(biāo)本質(zhì)是做平移
- 坐標(biāo)系
Threejs使用的是右手坐標(biāo)系礁蔗,x軸正方向向右,y軸正方向向上恒序,z軸由屏幕從里向外
- 運(yùn)動(dòng)原理
要么是攝像機(jī)移動(dòng)(camera.position)瘦麸,要么是物體移動(dòng)(object.position)
- 光源
1谁撼、環(huán)境光
環(huán)境光是經(jīng)過(guò)多次反射而來(lái)的光歧胁,無(wú)法確定其最初的方向。環(huán)境光是一種無(wú)處不在的光厉碟。環(huán)境光源放出的光線被認(rèn)為來(lái)自任何方向喊巍。因此,當(dāng)你僅為場(chǎng)景指定環(huán)境光時(shí)箍鼓,所有的物體無(wú)論法向量如何崭参,都將表現(xiàn)為同樣的明暗程度。
var light = new THREE.AmbientLight( 0xff0000 );
scene.add( light );
2款咖、點(diǎn)光源
由這種光源放出的光線來(lái)自同一點(diǎn)何暮,且方向輻射自四面八方
PointLight( color, intensity, distance )
3奄喂、聚光燈
這種光源的光線從一個(gè)錐體中射出,在被照射的物體上產(chǎn)生聚光的效果海洼。使用這種光源需要指定光的射出方向以及錐體的頂角α
THREE.SpotLight( hex, intensity, distance, angle, exponent )
- 材質(zhì)
材質(zhì)的本質(zhì)就是光
- 紋理
紋理的本質(zhì)就是圖片或者說(shuō)貼圖跨新,紋理主要用于豐富材質(zhì),
1坏逢、用圖片創(chuàng)建一個(gè)紋理:
// 創(chuàng)建一個(gè)幾何平面
var geometry = new THREE.PlaneGeometry( 500, 300, 1, 1 );
// 設(shè)置紋理坐標(biāo)
geometry.vertices[0].uv = new THREE.Vector2(0,0);
geometry.vertices[1].uv = new THREE.Vector2(2,0);
geometry.vertices[2].uv = new THREE.Vector2(2,2);
geometry.vertices[3].uv = new THREE.Vector2(0,2);
// 加載紋理
var texture = THREE.ImageUtils.loadTexture("textures/a.jpg",null,function(t)
{
});
// 將紋理運(yùn)用到材質(zhì)
var material = new THREE.MeshBasicMaterial({map:texture});
// 結(jié)合幾何體和材質(zhì)
var mesh = new THREE.Mesh( geometry,material );
scene.add( mesh );
2域帐、用 canvas 創(chuàng)建紋理
var geometry = new THREE.CubeGeometry(150, 150, 150);
texture = new THREE.Texture( canvas);
var material = new THREE.MeshBasicMaterial({map:texture});
texture.needsUpdate = true;
mesh = new THREE.Mesh( geometry,material );
scene.add( mesh );
需要注意的是在定義了紋理之后,我們將texture.needsUpdate設(shè)置為了true是整,如果不設(shè)置為true肖揣,那么紋理就不會(huì)更新,很可能你看到的是一個(gè)黑色的正方體浮入,原因是紋理沒(méi)有被載入之前龙优,就開(kāi)始渲染了,而渲染使用了默認(rèn)的材質(zhì)顏色
- 模型
模型是由面組成事秀,面分為三角形和四邊形面陋率。三角形和四邊形面組成了網(wǎng)格模型。在Three.js中用THREE.Mesh來(lái)表示網(wǎng)格模型秽晚。THREE.Mesh可以和THREE.Line相提并論,區(qū)別是THREE.Line表示的是線條赴蝇。THREE.Mesh表示面的集合菩浙。
THREE.Mesh = function ( geometry, material )
第一個(gè)參數(shù)geometry:是一個(gè)THREE.Geometry類型的對(duì)象,他是一個(gè)包含頂點(diǎn)和頂點(diǎn)之間連接關(guān)系的對(duì)象。
第二個(gè)參數(shù)Material:就是定義的材質(zhì)句伶。有了材質(zhì)就能夠讓模型更好看劲蜻,材質(zhì)會(huì)影響光照、紋理對(duì)Mesh的作用效果考余。
// VTK loader 使用示例
var material = new THREE.MeshLambertMaterial( { color:0xffffff, side: THREE.DoubleSide } );
var loader = new THREE.VTKLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var mesh = new THREE.Mesh( geometry, material );
mesh.position.setY( - 0.09 );
scene.add( mesh );
});
loader.load( "models/vtk/bunny.vtk" );
- 相機(jī)控制
通過(guò)鼠標(biāo)控制相機(jī) TrackballControls
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
camera.position.z = 0.2;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
- 陰影
陰影是增強(qiáng)三維場(chǎng)景效果的重要因素先嬉,但 Three.js 出于性能考慮,默認(rèn)關(guān)閉陰影
// 啟用陰影
renderer.shadowMap.enabled = true
// 并不是所有類型的光源能產(chǎn)生投影楚堤,不能產(chǎn)生投影的光源有:環(huán)境光(AmbientLight)疫蔓、半球光(HemisphereLight)
spotLight.castShadow = true
// 平面和立方體都能接受陰影
plane.receiveShadow = true
cube.receiveShadow = true
// 球體的陰影可以投射到平面和球體上
sphere.castShadow = true
// 更改渲染器的投影類型,默認(rèn)值是 THREE.PCFShadowMap
renderer.shadowMap.type = THREE.PCFSoftShadowMap
// 更改光源的陰影質(zhì)量身冬,默認(rèn)值是 512
spotLight.shadow.mapSize.width = 1024
spotLight.shadow.mapSize.height = 1024
- 霧化
// Fog( hex, near, far )衅胀,線性霧化。
// near 表示哪里開(kāi)始應(yīng)用霧化效果(攝像機(jī)為 0)
// far 表示哪里的霧化濃度為 1酥筝。若某物體在該距離后滚躯,則其表現(xiàn)為霧的顏色。當(dāng)霧的顏色和渲染器的背景色相同時(shí),則表現(xiàn)為消失(實(shí)為顏色相同)掸掏。
scene.fog = new THREE.Fog( 0xffffff, 0.015, 100 )
// FogExp2( hex, density )茁影,指數(shù)霧化
// density 是霧化強(qiáng)度
scene.fog = new THREE.FogExp2( 0xffffff, 0.01 )
// 霧化效果默認(rèn)是全局影響的,若某個(gè)材質(zhì)不受霧化效果影響丧凤,則可為材質(zhì)的 fog 屬性設(shè)置為 false(默認(rèn)值 true)
var material = new THREE.Material({
fog: false
})
- 渲染器剔除模式
在 Three.js 中呼胚,材質(zhì)默認(rèn)只應(yīng)用在正面(THREE.FrontSide),即當(dāng)你旋轉(zhuǎn)物體(或攝像機(jī))查看物體的背面時(shí)息裸,它會(huì)因?yàn)槲幢粦?yīng)用材質(zhì)而變得透明(即效果與 CSS3 backface-visibility: hidden 一樣)蝇更。因此,當(dāng)你想讓物體正反兩面均應(yīng)用材質(zhì)呼盆,則需要在創(chuàng)建材質(zhì)時(shí)聲明 side 屬性為 THREE.DoubleSide:
var material = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide // 其他值:THREE.FrontSide(默認(rèn)值)年扩、THREE.BackSide
})
這個(gè)模式應(yīng)用在3D看房時(shí)比較好用
- 聲音 Audio
音頻也是 3D 的,它會(huì)受到攝像機(jī)的距離影響:
1访圃、聲源離攝像機(jī)的距離決定著聲音的大小厨幻。
2、聲源在攝像機(jī)左右側(cè)的位置分別決定著左右揚(yáng)聲器聲音的大小腿时。