本文創建的天空盒是用六張圖片來創建的。筆者會論述兩種方法來創建,都是最簡單基本的方法,不涉及着色器的使用。
一種是創建一個盒子,然后將圖片作為盒子6個面的紋理貼上來創建。
另一種則是簡單的將紋理作為場景的背景來創建。
兩種方法視覺效果是幾乎沒區別的,會給人身臨其境的效果,感覺身處在這個3維空間里,最明顯的區別就在於當你在用鼠標滾輪縮進的時候,天空盒會“原形畢露”,暴露出其盒子的本性,視覺效果原理展現在你的眼前。如圖所示:
而作為背景的方法創建的話,則無論你怎么縮進,都不會“原形畢露”。
當然,縮進的設置我們是可以自己調整的,規定縮進的范圍,用第一種方法也是可以不暴露出盒子的原型的。
好,接下來我們來看代碼部分。
<div id="WebGL-output"></div> <script src="../build/three.js"></script> <script src="../examples/js/controls/OrbitControls.js"></script>
第一步是引用文件,我們是用Three.js來創建天空盒,所以第一個引用的是three.js這個文件,第二引用的文件是OrbitControls.js,這里面的函數是我們用來操控相機的,你可以通過調用這個文件里的函數在天空盒中實現360°的轉換視角來觀看,前文所述的你如果要調整縮進的話,也是調用里面的函數。
至於第一行的div,是作為我們three.js的輸出對象。
寫完引用文件,接下來看下正文代碼的結構。
1 <script> 2 3 var scene, camera, renderer; 4 var container, controls; 5 6 init(); 7 animate(); 8 9 // FUNCTIONS 10 function init() 11 { 12 ······ 13 14 } 15 16 function animate() 17 { 18 ······ 19 } 20 21 function update() 22 { 23 ······ 24 } 25 26 function render() 27 { 28 ······ 29 } 30 31 </script>
第一步創建會用到的全局變量
three.js不可缺少的三部分:scene(場景), camera(相機), renderer(渲染器);
至於另外兩個變量我們在代碼中去理解。筆者在此就不多述了。
核心部分是init()函數,先創立三維場景基本要素:
1 // 創建場景 2 scene = new THREE.Scene(); 3 // 定義透視相機的四個參數變量 4 var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; 5 var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000; 6 //創建相機 7 camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); 8 camera.position.set(0,150,400);//將相機的位置擺放在(0,150,400)的位置。這里位置你可以更改以下,放在(0,0,400)也是可以的 9 camera.lookAt(scene.position);//讓相機對着場景中央 10 //將相機加入場景之中 11 scene.add(camera); 12 13 //設置渲染器 14 renderer = new THREE.WebGLRenderer( {antialias:true} );//設置為抗鋸齒 15 renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);//設置渲染器渲染的場景大小 16 17 container = document.getElementById( 'WebGL-output' ); 18 container.appendChild( renderer.domElement ); 19 /*renderer的domElement元素,表示渲染器中的畫布,所有的渲染都是畫在domElement上的,所以這里的appendChild表示將這個domElement掛接在id=WebGL-output的div下面,這樣渲染的結果就能夠在頁面中顯示了。*/ 20 21 //再設置相機控件,這行代碼能讓我們360°的旋轉相機 22 controls = new THREE.OrbitControls( camera, renderer.domElement );
接着是創建天空盒的代碼:
1 var path = "../examples/textures/cube/Park3Med/";//設置路徑 2 var directions = ["px", "nx", "py", "ny", "pz", "nz"];//獲取對象 3 var format = ".jpg";//格式 4 //創建盒子,並設置盒子的大小為( 5000, 5000, 5000 ) 5 var skyGeometry = new THREE.BoxGeometry( 5000, 5000, 5000 ); 6 //設置盒子材質 7 var materialArray = []; 8 for (var i = 0; i < 6; i++) 9 materialArray.push( new THREE.MeshBasicMaterial({ 10 map: THREE.ImageUtils.loadTexture( path + directions[i] + format ),//將圖片紋理貼上 11 side: THREE.BackSide/*鏡像翻轉,如果設置鏡像翻轉,那么只會看到黑漆漆的一片,因為你身處在盒子的內部,所以一定要設置鏡像翻轉。*/ 12 })); 13 var skyMaterial = new THREE.MeshFaceMaterial( materialArray ); 14 var skyBox = new THREE.Mesh( skyGeometry, skyMaterial );//創建一個完整的天空盒,填入幾何模型和材質的參數 15 scene.add( skyBox );//在場景中加入天空盒
注意directions[]數組中的圖片順序是有要求而不是隨意的!否則加載的效果會錯亂。這張圖片會幫助你更好的理解:
剩下的尾巴部分:
1 function animate() 2 { 3 requestAnimationFrame( animate );//渲染循環 4 render(); 5 update(); 6 } 7 8 function update() 9 { 10 controls.update();//實時更新相機操作 11 } 12 13 function render() 14 { 15 renderer.render( scene, camera );//實時渲染 16 }
另一種作為背景的方法的代碼如下:
1 var path = "textures/cube/Park3Med/"; //設置路徑 2 var format = '.jpg'; //設定格式 3 var urls = [ 4 path + 'px' + format, path + 'nx' + format, 5 path + 'py' + format, path + 'ny' + format, 6 path + 'pz' + format, path + 'nz' + format 7 ]; 8 var textureCube = new THREE.CubeTextureLoader().load( urls ); 9 10 scene.background = textureCube; //作為背景貼圖
還有另一種更簡潔的寫法是:
1 scene.background = new THREE.CubeTextureLoader() 2 .setPath( 'textures/cube/Park3Med/' ) 3 .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
兩種方法只需要更換這部分代碼即可。
以下給出全部代碼:
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title>Skybox</title> 6 <style> 7 body { 8 background:#777; 9 padding:0; 10 margin:0; 11 font-weight: bold; 12 overflow:hidden; 13 } 14 </style> 15 </head> 16 <body> 17 18 <div id="WebGL-output"></div> 19 <script src="../build/three.js"></script> 20 <script src="../examples/js/controls/OrbitControls.js"></script> 21 22 <script> 23 24 var scene, camera, renderer; 25 var container, controls; 26 27 28 init(); 29 animate(); 30 31 // FUNCTIONS 32 function init() 33 { 34 // SCENE 35 scene = new THREE.Scene(); 36 // CAMERA 37 var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; 38 var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000; 39 camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); 40 camera.position.set(0,150,400); 41 camera.lookAt(scene.position); 42 43 scene.add(camera); 44 45 // RENDERER 46 47 renderer = new THREE.WebGLRenderer( {antialias:true} ); 48 renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); 49 50 container = document.getElementById( 'output' ); 51 container.appendChild( renderer.domElement ); 52 53 controls = new THREE.OrbitControls( camera, renderer.domElement ); 54 55 // LIGHT 56 var light = new THREE.PointLight(0xffffff); 57 light.position.set(0,250,0); 58 scene.add(light); 59 // FLOOR 60 61 var path = "../examples/textures/cube/Park3Med/"; 62 var directions = ["px", "nx", "py", "ny", "pz", "nz"]; 63 var format = ".jpg"; 64 var skyGeometry = new THREE.BoxGeometry( 5000, 5000, 5000 ); 65 66 var materialArray = []; 67 for (var i = 0; i < 6; i++) 68 materialArray.push( new THREE.MeshBasicMaterial({ 69 map: THREE.ImageUtils.loadTexture( path + directions[i] + format ), 70 side: THREE.BackSide 71 })); 72 var skyMaterial = new THREE.MeshFaceMaterial( materialArray ); 73 var skyBox = new THREE.Mesh( skyGeometry, skyMaterial ); 74 //skyBox.scale.x=-1;也是鏡像翻轉,與上面的side一個效果 75 scene.add( skyBox ); 76 77 } 78 79 function animate() 80 { 81 requestAnimationFrame( animate ); 82 render(); 83 update(); 84 } 85 86 function update() 87 { 88 controls.update(); 89 } 90 91 function render() 92 { 93 renderer.render( scene, camera ); 94 } 95 96 </script> 97 </body> 98 </html>
以上有一段代碼是燈光的設置加入,這里可以注釋掉,不影響天空盒的效果。但是如果你要在天空盒中加入物體,則需要設置燈光,否則加入場景的物體將會是黑色的。
以上就是筆者的一些見解,若有不對的對方,歡迎指正。