iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 11
0
Modern Web

WebGL 與 Three.js 初探系列 第 11

[Day11 聖誕節特輯] Three.js - 畫一棵幾何聖誕樹吧!

今天是聖誕節,讓我們一起畫一棵簡單的聖誕樹吧!

基本場景設定

我們設置一下基本的場景

const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
const camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0,0, 40);


function init() {	
	renderer.shadowMap.enabled = true;
	var hemisphereLight = new THREE.HemisphereLight(0xaaaaaa,0x000000, .9)
	var ambientLight = new THREE.AmbientLight(0xdc8874, .5);
	var light = new THREE.DirectionalLight( new THREE.Color('rgb(200,200,200)') ); // soft white ligh t

	light.position.set(20, 10, 10);
	scene.add(light);
	scene.add(hemisphereLight);
	scene.add(ambientLight);
	renderer.setSize(window.innerWidth, window.innerHeight);
	document.body.appendChild(renderer.domElement);
}
init();

1. 尋找合適的幾何圖形

我們的聖誕樹可以簡化為幾個三角錐組合起來的形狀。

剛好在 ThreeJS 當中有個 ConeGeometry 建構式,來看看它的形狀

如果我們建立三個三角錐,然後藉由 scale 的方式組合起來呢?

function Tree () {
	this.body = new THREE.Object3D();
	this.body.castShadow = true;
	this.body.receiveShadow = true;
	this.body.name = 'tree';

	var geometry = new THREE.ConeGeometry( 10, 20, 17 );
	var material = new THREE.MeshPhongMaterial({color: 0x0d7753, shading: THREE.FlatShading });
	var cone = new THREE.Mesh( geometry, material );

	cone.receiveShadow = true;
	cone.receiveShadow = true;
	var cone2 = cone.clone();
	var cone3 = cone.clone();
	cone.name = 'tree';
	cone.position.set(0, 20, 0);
	cone2.scale.set(1.2, 1.2, 1.2);
	cone2.position.set(0, 10, 0);

	cone3.scale.set(1.5, 1.5, 1.5);
	cone3.position.set(0, 0, 0);

	this.body.add(cone);
	this.body.add(cone2);
	this.body.add(cone3);
	
	return this;
}

我們透過 scale 函數調整大小,並且做了三層。看一下效果如何:
http://ithelp.ithome.com.tw/upload/images/20161225/201035656NYHMXsriM.png

雖然簡單,不過意外地蠻有樹的感覺的,看來就算是工程師,只要利用巧思也可以做出一個不錯看的幾何圖形!

加入樹幹

樹幹我們可以用很簡單的 CubeGeometry 創造出來。
http://ithelp.ithome.com.tw/upload/images/20161225/20103565uC0Rr9NKCX.png

現在這棵聖誕樹雛型已經出來,只剩下裝飾而已了!

加入星星

Loader 的 API 還沒有介紹到,不過 Three.js 可以讓我們用 obj 的檔案載入模型,所以會建模的朋友們,也可以先建模好之後再拿來使用哦!

star model

const loader = new THREE.OBJLoader();
loader.load('../../assets/star.obj', function(obj) {
	object = obj;

	obj.children[2].position.set(0, 28, 5);
	obj.children[2].material = new THREE.MeshPhongMaterial({ color: 0xF3BB02})
	scene.add(obj.children[2]);
	scene.add(tree.body);
	renderer.render(scene, camera);
	anime();
});

http://ithelp.ithome.com.tw/upload/images/20161225/20103565xXTpYLl1Z6.png

加入星星後看起來好一些了!不過裝飾的部分,我們今天就先省略吧XD。

加入動畫

有了基本形狀之後,我們可以加入一些簡單的動畫

function anime() {
	const star = scene.getObjectByName('tree.star');
	const tree = scene.getObjectByName('tree');
	tree.rotation.y += Math.PI / 500;
	star.rotation.y += Math.PI / 100;
	renderer.render( scene, camera );	
	animationID = requestAnimationFrame(anime);
}

這邊只是簡單地讓樹旋轉而已。原本想要呈現更豐富的效果,但礙於目前 Three 的掌握度還不夠,而且時程上太趕了...,所以這邊只是簡單的做出雛形而已。

下雪

為了讓氣氛更逼真,我使用了 three.js 的 Points System 來製作雪景,不過看起來很不逼真QQ,有很多參數還要再調整。

最後,附上應景的聖誕歌曲

加入應景的歌曲。加入 audio

demo-christmas

結論

今天是聖誕節,除了想要帶給大家歡樂的氣氛外,也順便學習一下如何用簡單的幾何形狀拼湊出還不算太糟糕的效果(至少比一個正方體轉來轉去好多了吧...),不過目前因為時間不太夠的關係,只能夠用比較醜的方式組織代碼。

希望能夠給各位不同的頁面呈現方式,下次如果煩惱頁面要如何呈現,或是用 CSS 難以達到的特效,不妨考慮看看這門強大的框架,或許公司的轉換率就取決於你的 landing page 多麽吸引人囉!

最後,給各位參賽鐵人們跟讀者們,聖誕節還待在電腦前 coding 實在太偉大了。

聖 誕 快 樂


上一篇
[Day10] 寫在 Three.js 之前 - 投影基礎
下一篇
[Day12] 寫在 Three.js 之前 (2) - 光源淺談
系列文
WebGL 與 Three.js 初探30

尚未有邦友留言

立即登入留言