three.js 創(chuàng)建一個場景

2023-02-16 17:20 更新

這一部分將對three.js來做一個簡要的介紹;我們將開始搭建一個場景,其中包含一個正在旋轉(zhuǎn)的立方體。頁面下方有一個已經(jīng)完成的例子,當你遇到麻煩,或者需要幫助的時候,可以看一看。

開始之前

在開始使用three.js之前,你需要一個地方來顯示它。將下列HTML代碼保存為你電腦上的一個HTML文件,同時將three.js復(fù)制到該HTML文件所在的目錄下的js/目錄下,然后在你的瀏覽器中打開這個HTML文件。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script src="js/three.js"></script>
		<script>
			// Our Javascript will go here.
		</script>
	</body>
</html>

好了,接下來的所有代碼將會寫入到空的<script>標簽中。

創(chuàng)建一個場景

為了真正能夠讓你的場景借助three.js來進行顯示,我們需要以下幾個對象:場景、相機和渲染器,這樣我們就能透過攝像機渲染出場景。

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

我們花一點點時間來解釋一下這里發(fā)生了什么。我們現(xiàn)在建立了場景、相機和渲染器。

three.js里有幾種不同的相機,在這里,我們使用的是PerspectiveCamera(透視攝像機)。

第一個參數(shù)是視野角度(FOV)。視野角度就是無論在什么時候,你所能在顯示器上看到的場景的范圍,它的單位是角度(與弧度區(qū)分開)。

第二個參數(shù)是長寬比(aspect ratio)。 也就是你用一個物體的寬除以它的高的值。比如說,當你在一個寬屏電視上播放老電影時,可以看到圖像仿佛是被壓扁的。

接下來的兩個參數(shù)是近截面(near)和遠截面(far)。 當物體某些部分比攝像機的遠截面遠或者比近截面近的時候,該這些部分將不會被渲染到場景中?;蛟S現(xiàn)在你不用擔心這個值的影響,但未來為了獲得更好的渲染性能,你將可以在你的應(yīng)用程序里去設(shè)置它。

接下來是渲染器。這里是施展魔法的地方。除了我們在這里用到的WebGLRenderer渲染器之外,Three.js同時提供了其他幾種渲染器,當用戶所使用的瀏覽器過于老舊,或者由于其他原因不支持WebGL時,可以使用這幾種渲染器進行降級。

除了創(chuàng)建一個渲染器的實例之外,我們還需要在我們的應(yīng)用程序里設(shè)置一個渲染器的尺寸。比如說,我們可以使用所需要的渲染區(qū)域的寬高,來讓渲染器渲染出的場景填充滿我們的應(yīng)用程序。因此,我們可以將渲染器寬高設(shè)置為瀏覽器窗口寬高。對于性能比較敏感的應(yīng)用程序來說,你可以使用setSize傳入一個較小的值,例如window.innerWidth/2window.innerHeight/2,這將使得應(yīng)用程序在渲染時,以一半的長寬尺寸渲染場景。

如果你希望保持你的應(yīng)用程序的尺寸,但是以較低的分辨率來渲染,你可以在調(diào)用setSize時,將updateStyle(第三個參數(shù))設(shè)為false。例如,假設(shè)你的<canvas> 標簽現(xiàn)在已經(jīng)具有了100%的寬和高,調(diào)用setSize(window.innerWidth/2, window.innerHeight/2, false)將使得你的應(yīng)用程序以一半的分辨率來進行渲染。

最后一步很重要,我們將renderer(渲染器)的dom元素(renderer.domElement)添加到我們的HTML文檔中。這就是渲染器用來顯示場景給我們看的<canvas>元素。

“嗯,看起來很不錯,那你說的那個立方體在哪兒?”接下來,我們就來添加立方體。

const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;

要創(chuàng)建一個立方體,我們需要一個BoxGeometry(立方體)對象. 這個對象包含了一個立方體中所有的頂點(vertices)和面(faces)。未來我們將在這方面進行更多的探索。

接下來,對于這個立方體,我們需要給它一個材質(zhì),來讓它有顏色。Three.js自帶了幾種材質(zhì),在這里我們使用的是MeshBasicMaterial。所有的材質(zhì)都存有應(yīng)用于他們的屬性的對象。在這里為了簡單起見,我們只設(shè)置一個color屬性,值為0x00ff00,也就是綠色。這里所做的事情,和在CSS或者Photoshop中使用十六進制(hex colors)顏色格式來設(shè)置顏色的方式一致。

第三步,我們需要一個Mesh(網(wǎng)格)。 網(wǎng)格包含一個幾何體以及作用在此幾何體上的材質(zhì),我們可以直接將網(wǎng)格對象放入到我們的場景中,并讓它在場景中自由移動。

默認情況下,當我們調(diào)用scene.add()的時候,物體將會被添加到(0,0,0)坐標。但將使得攝像機和立方體彼此在一起。為了防止這種情況的發(fā)生,我們只需要將攝像機稍微向外移動一些即可。

渲染場景

現(xiàn)在,如果將之前寫好的代碼復(fù)制到HTML文件中,你不會在頁面中看到任何東西。這是因為我們還沒有對它進行真正的渲染。為此,我們需要使用一個被叫做“渲染循環(huán)”(render loop)或者“動畫循環(huán)”(animate loop)的東西。

function animate() {
	requestAnimationFrame( animate );
	renderer.render( scene, camera );
}
animate();

在這里我們創(chuàng)建了一個使渲染器能夠在每次屏幕刷新時對場景進行繪制的循環(huán)(在大多數(shù)屏幕上,刷新率一般是60次/秒)。如果你是一個瀏覽器游戲開發(fā)的新手,你或許會說“為什么我們不直接用setInterval來實現(xiàn)刷新的功能呢?”當然啦,我們的確可以用setInterval,但是,requestAnimationFrame有很多的優(yōu)點。最重要的一點或許就是當用戶切換到其它的標簽頁時,它會暫停,因此不會浪費用戶寶貴的處理器資源,也不會損耗電池的使用壽命。

使立方體動起來

在開始之前,如果你已經(jīng)將上面的代碼寫入到了你所創(chuàng)建的文件中,你可以看到一個綠色的方塊。讓我們來做一些更加有趣的事 —— 讓它旋轉(zhuǎn)起來。

將下列代碼添加到animate()函數(shù)中renderer.render調(diào)用的上方:

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

這段代碼每幀都會執(zhí)行(正常情況下是60次/秒),這就讓立方體有了一個看起來很不錯的旋轉(zhuǎn)動畫。基本上來說,當應(yīng)用程序運行時,如果你想要移動或者改變?nèi)魏螆鼍爸械臇|西,都必須要經(jīng)過這個動畫循環(huán)。當然,你可以在這個動畫循環(huán)里調(diào)用別的函數(shù),這樣你就不會寫出有上百行代碼的animate函數(shù)。

結(jié)果

祝賀你!你現(xiàn)在已經(jīng)成功完成了你的第一個Three.js應(yīng)用程序。雖然它很簡單,但現(xiàn)在你已經(jīng)有了一個入門的起點。

下面是完整的代碼,可在live example運行、編輯;運行或者修改代碼有助于你更好的理解它是如何工作的。

<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script src="js/three.js"></script>
		<script>
			const scene = new THREE.Scene();
			const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

			const renderer = new THREE.WebGLRenderer();
			renderer.setSize( window.innerWidth, window.innerHeight );
			document.body.appendChild( renderer.domElement );

			const geometry = new THREE.BoxGeometry( 1, 1, 1 );
			const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
			const cube = new THREE.Mesh( geometry, material );
			scene.add( cube );

			camera.position.z = 5;

			function animate() {
				requestAnimationFrame( animate );

				cube.rotation.x += 0.01;
				cube.rotation.y += 0.01;

				renderer.render( scene, camera );
			};

			animate();
		</script>
	</body>
</html>


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號