用three.js创建一个简易的天空盒


本文创建的天空盒是用六张图片来创建的。笔者会论述两种方法来创建,都是最简单基本的方法,不涉及着色器的使用。
一种是创建一个盒子,然后将图片作为盒子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>

以上有一段代码是灯光的设置加入,这里可以注释掉,不影响天空盒的效果。但是如果你要在天空盒中加入物体,则需要设置灯光,否则加入场景的物体将会是黑色的。
以上就是笔者的一些见解,若有不对的对方,欢迎指正。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM