three.js基礎(chǔ)結(jié)構(gòu)
目錄
一個three.js項目至少需要的東西有——
[ ] scene:場景
[ ] camera:攝像機
[ ] render:渲染器
[ ] light:燈光
可能需要的有——
[ ] controls:攝像機控制器
[ ] raycaster:點擊射線,用于點擊事件
[ ] loader:加載器组去,特殊的物體例如模型需要使用加載器账胧,而且不同格式的模型需要不同的加載器
[ ] object:場景內(nèi)的物體對象
場景
在three.js中较鼓,場景是作為最外層容器存在的歼跟,它相當于html中的window對象鹊漠,所有three.js中的對象愧驱,都可以在scene中找到派桩。
它作為three.js的載體泼差,是一個可自定義的三維模擬空間,定義方式如下(改代碼使用MVC結(jié)構(gòu))——
initScene: function() {
// 聲明場景
appModel.threeSceneObject.scene = new THREE.Scene();
// 可選擇呵俏,是否啟動霧化效果堆缘,參數(shù)1是霧的顏色,參數(shù)2普碎,3是霧化起始距離和最遠距離吼肥,是以場景的坐標點(0,0,0)為起始點。
appModel.threeSceneObject.scene.fog = new THREE.Fog(0xffffff, 200, 1300);
}
攝像機
攝像機随常,或者說它是視角潜沦,同一個場景上,不同的視角看到的內(nèi)容自然會不一樣绪氛。視角和場景不一樣唆鸡,不僅僅是需要定義,還需要在渲染器`render`中枣察,進行進一步的設(shè)定争占,這里先不講,只要知道這個攝像機的“攝像功能”需要被不停的執(zhí)行序目,才能讓三維的場景看起來動作流暢臂痕。
這個很好理解——攝像機照出來的是照片,是靜止的猿涨。但是我們看到的是場景握童,里面的內(nèi)容是可以動的,那么這要如何實現(xiàn)叛赚?自然是參考動畫的制作——連續(xù)切換的靜止圖片組成一個動圖澡绩。
攝像機的初始化方式如下:
// 初始化攝像機
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
// 設(shè)置攝像機位置
camera.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);
攝像機的伙伴,control控制器
攝像機也是一個物體俺附,一個對象肥卡,但是一般的攝像機只能設(shè)置一些靜態(tài)屬性,如位置事镣,朝向等等參數(shù)步鉴。但是,使用control插件璃哟,我們就可以動態(tài)的操控攝像機氛琢,如:
OrbitControls:軌道控制器,以中心點(可自定義其他的點)為圓心随闪,左右拉動場景可以使攝像機圍繞著這個中心點旋轉(zhuǎn)阳似,旋轉(zhuǎn)半徑在初始化的時候設(shè)定。
FlyControls:飛行控制器蕴掏,第一人稱視角控制器障般,一版的PFS射擊游戲視角,可以使用asdw進行前后左右操控移動盛杰。
燈光
場景中燈光也是必要的挽荡,沒有光,場景中的任何東西就處于“看不見”狀態(tài)即供,就像站在在一片大地上定拟,卻沒有太陽,理所當然看到的是一片漆黑逗嫡。
燈光有三種光源青自,平行光,點光源驱证,聚光燈光源延窜。
平行光類似于太陽光,點光源類似于燈泡抹锄,聚光燈如其名是個聚光燈逆瑞。三種光源的效果差距在于渲染物體時物體表面上的光的范圍。如果物體正對于太陽光伙单,那么它對著平行光的面上每一個部分接收到的“陽光”都是一樣的获高。而點光源在同樣情況下,光在投射到物體表面的中心點處最強吻育,然后逐漸衰弱念秧。聚光燈則處于兩者之間,在某一個照射范圍內(nèi)布疼,內(nèi)部的光可以看成是平行光摊趾,而超過這個范圍,則完全看不到缎除。
大部分情況下严就,點光源和平行光并沒有明顯的區(qū)別,不過在使用另一個系統(tǒng)——影子之后器罐,差距就會出來了梢为。太陽光下的影子和點光源下的影子差距還是挺大的。
燈光的初始化如下:
// 點光源
var light2 = new THREE.PointLight(0xFFFFFF);
light2.position.set(6, 6, 24);
scene.add(light2);
// 平行光
var sun1 = new THREE.DirectionalLight(0xffffff);
sun1.position.set(-1000, 500, -1000);
//sun1.castShadow = true;
appModel.threeSceneObject.scene.add(sun1);
可以看到轰坊,兩者的初始化的方式幾乎一摸一樣铸董。陽光的渲染原理其實很簡單:將陽光的顏色和物體的顏色進行融合,同時顯示面對陽光的對象的部分內(nèi)容肴沫。所以將上述代碼的光色改成紅色粟害,就會發(fā)現(xiàn)物體也會被染色。
陽光照射不到的部分會顯示黑色颤芬。
渲染器
渲染器的核心方法只有一句:
render.render(scene, camera);
這句話會使得整個場景的內(nèi)容刷新一次悲幅,所以這個方法需要放在requestAnimationFrame中不停地執(zhí)行套鹅。
條用渲染器的render方法會刷新內(nèi)容,這個內(nèi)容可以是某個物體的位置移動汰具,翻轉(zhuǎn)卓鹿,變形,例如攝像機留荔,單純的物體吟孙,也可以是隨著時間而執(zhí)行的某種代碼,如添加倒計時聚蝶,時間一到便刪除某個物體杰妓。
<strong>可以說,three中所有動態(tài)活動碘勉,不管是場景視角的移動巷挥,還是物體的屬性變動,其代碼都會在這里執(zhí)行验靡。</strong>
最基礎(chǔ)的render方法如下:
render: function() {
render.render(scene, camera);
requestAnimationFrame(appController.render);
},
<strong> 第一行是一個render方法句各,所有的動態(tài)代碼將寫在這個方法中</strong>
<strong>第二行有兩個render,第一個render是render渲染器晴叨,第二個是渲染器內(nèi)部的方法凿宾,所以這三行的render的意義其實都不一樣。這個render傳入的是當前的場景對象和攝像機對象兼蕊,通過他們three會計算出當前場景的"截圖"</strong>
<strong>第三行使用requestAnimationFrame方法初厚,瘋狂調(diào)用render方法自身,即第一行的render孙技,達到不停的截圖产禾,串成一個動畫的效果</strong>
而render自身的初始化方法是:
// new 一個render對象
render = new THREE.WebGLRenderer({
antialias: true
});
// 設(shè)置render分辨率
render.setPixelRatio(window.devicePixelRatio);
// 設(shè)置render渲染范圍大小
render.setSize(window.innerWidth, window.innerHeight);
// 將整個three場景轉(zhuǎn)成canvas,放到id為container的div中牵啦。
document.getElementById('container').appendChild(render.domElement);
// 設(shè)置場景的渲染顏色和透明度
render.setClearColor(0xFFFFFF, 1.0);
<strong>這一段代碼優(yōu)先級非常高亚情,使用three的時候,請將其第一個初始化哈雏。</strong>