本文创建的天空盒是用六张图片来创建的。笔者会论述两种方法来创建,都是最简单基本的方法,不涉及着色器的使用。
一种是创建一个盒子,然后将图片作为盒子6个面的纹理贴上来创建。
另一种则是简单的将纹理作为场景的背景来创建。
两种方法视觉效果是几乎没区别的,会给人身临其境的效果,感觉身处在这个3维空间里,最明显的区别就在于当你在用鼠标滚轮缩进的时候,天空盒会“原形毕露”,暴露出其盒子的本性,视觉效果原理展现在你的眼前。如图所示:
而作为背景的方法创建的话,则无论你怎么缩进,都不会“原形毕露”。
当然,缩进的设置我们是可以自己调整的,规定缩进的范围,用第一种方法也是可以不暴露出盒子的原型的。
好,接下来我们来看代码部分。
第一步是引用文件,我们是用Three.js来创建天空盒,所以第一个引用的是three.js这个文件,第二引用的文件是OrbitControls.js,这里面的函数是我们用来操控相机的,你可以通过调用这个文件里的函数在天空盒中实现360°的转换视角来观看,前文所述的你如果要调整缩进的话,也是调用里面的函数。
至于第一行的div,是作为我们three.js的输出对象。
写完引用文件,接下来看下正文代码的结构。
1
2
3 varscene, camera, renderer;4 varcontainer, controls;5
6 init();7 animate();8
9 //FUNCTIONS
10 functioninit()11 {12 ······13
14 }15
16 functionanimate()17 {18 ······19 }20
21 functionupdate()22 {23 ······24 }25
26 functionrender()27 {28 ······29 }30
31
第一步创建会用到的全局变量
three.js不可缺少的三部分:scene(场景), camera(相机), renderer(渲染器);
至于另外两个变量我们在代码中去理解。笔者在此就不多述了。
核心部分是init()函数,先创立三维场景基本要素:
1 //创建场景
2 scene = newTHREE.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 = newTHREE.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( newTHREE.MeshBasicMaterial({10 map: THREE.ImageUtils.loadTexture( path + directions[i] + format ),//将图片纹理贴上
11 side: THREE.BackSide/*镜像翻转,如果设置镜像翻转,那么只会看到黑漆漆的一片,因为你身处在盒子的内部,所以一定要设置镜像翻转。*/
12 }));13 var skyMaterial = newTHREE.MeshFaceMaterial( materialArray );14 var skyBox = new THREE.Mesh( skyGeometry, skyMaterial );//创建一个完整的天空盒,填入几何模型和材质的参数
15 scene.add( skyBox );//在场景中加入天空盒
注意directions[]数组中的图片顺序是有要求而不是随意的!否则加载的效果会错乱。这张图片会帮助你更好的理解:
剩下的尾巴部分:
1 functionanimate()2 {3 requestAnimationFrame( animate );//渲染循环
4 render();5 update();6 }7
8 functionupdate()9 {10 controls.update();//实时更新相机操作
11 }12
13 functionrender()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' +format7 ];8 var textureCube = newTHREE.CubeTextureLoader().load( urls );9
10 scene.background = textureCube; //作为背景贴图
还有另一种更简洁的写法是:
1 scene.background = newTHREE.CubeTextureLoader()2 .setPath( 'textures/cube/Park3Med/')3 .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
两种方法只需要更换这部分代码即可。
以下给出全部代码:
1
2
3
4
5
Skybox6
7 body {8 background:#777;9 padding:0;10 margin:0;11 font-weight: bold;12 overflow:hidden;13 }14
15
16
17
18
19
20
21
22
23
24 varscene, camera, renderer;25 varcontainer, controls;26
27
28 init();29 animate();30
31 //FUNCTIONS
32 functioninit()33 {34 //SCENE
35 scene = newTHREE.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 = newTHREE.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 = newTHREE.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( newTHREE.MeshBasicMaterial({69 map: THREE.ImageUtils.loadTexture( path + directions[i] +format ),70 side: THREE.BackSide71 }));72 var skyMaterial = newTHREE.MeshFaceMaterial( materialArray );73 var skyBox = newTHREE.Mesh( skyGeometry, skyMaterial );74 //skyBox.scale.x=-1;也是镜像翻转,与上面的side一个效果
75 scene.add( skyBox );76
77 }78
79 functionanimate()80 {81 requestAnimationFrame( animate );82 render();83 update();84 }85
86 functionupdate()87 {88 controls.update();89 }90
91 functionrender()92 {93 renderer.render( scene, camera );94 }95
96
97
98
以上有一段代码是灯光的设置加入,这里可以注释掉,不影响天空盒的效果。但是如果你要在天空盒中加入物体,则需要设置灯光,否则加入场景的物体将会是黑色的。
以上就是笔者的一些见解,若有不对的对方,欢迎指正。