HTML5+WebGL的Web3D展⽰
下图是客户给的⼀张的效果参考图,希望机房⾄少能达到下⾯的3D效果。
懂的⼈都知道,这可是⼀张设计公司出的装修效果图啊,就算是⽤max建模,也需要⼤量的⼯作,何况
咱可是程序员在做数据中⼼的可视化项⽬啊。静下⼼来思考,那就先从搭建⼀个webGL的场景开始吧。
WebGL基本场景搭建
在html5⾥⾯使⽤3D已经不是什么⾼深技术,它的基础是WebGL,⼀个OpenGL的浏览器⼦集,⽀持⼤部分主要3D功能接⼝。⽬前最新的浏览器都有⽐较好的⽀持,IE需要到11(是的,你没有看错)。
要在浏览器⾥⾯使⽤webGL,就要研究webGL相关的技术和⽤法。做3D应⽤并不是⼀件轻松的事。就算最简单的搭建⼀下webGL场景,也需要下⾯这些代码:
var width = window.innerWidth; var height= window.innerHeight; var container = document.( 'div' ); document.body.( container ); var webglcanvas = document.('canvas'); container.(webglcanvas); var gl =
gl.clearColor(0.4, 0.4, 0.7, 1); gl.clear ( gl.COLOR_BUFFER_BIT ); setTimeout( function(){updateFrame()}, 20); } setTimeout( function(){ updateFrame(); }, 20);
和html⼀样,需要先创建⼀个canvas元素,并获得其webgl上下⽂:
var gl = Context("experimental-webgl");
然后在⼀个updateFrame的函数中,像html5的2D context⼀样,去绘制3D的内容。
另外,要再起⼀个死循环,每隔**毫秒调⽤⼀次这个updateFrame函数来重绘场景。和2D不同,3D场景⾥⾯的变化是随时随地的,所以需要不停刷新,就像播放电影或视频,静⽌不动的画⾯基本没有,所以死循环刷新基本是必要的。不过实际项⽬使⽤中会有很多优化,尽量做到“按需刷新”,节省cpu和移动设备电量。有感兴趣的同学,哥可以单独写⽂章介绍。这段程序基本上什么也没做,就画了⼀个静⽌不动的区域,如下图:
虽然看不见任何3D的内容,不过它已经是⼀个最简单的webgl程序了。我们的3D机房,也就是在这上⾯不断丰富⽽已。
对象封装
要做项⽬,搭建下去⼯作量太⼤了,时间周期也不允许。使⽤第三⽅辅助⼯具是不可避免的,像Three.js, twaver.js都是选择。这些⼯具都可以提供3D的基本对象和各种特效,当然这都不是最主要的,主要是如何利⽤它做出我想要的效果:好看。为了避免⼤量修改代码,在项⽬⾥做了⼀些封装,
即把原始3D的⽴⽅体等对象进⾏进⼀步封装,让⼀个json 数据就可以提供这些对象的定义。这样使⽤起来就⽐较⽅便了。json⼤致结构如下:
var json={ objects: [{ name: '地板', … },{ … }], }
下⾯我们逐⼀来看这些3D对象是怎么进⾏美化的,过程可能稍显啰嗦,跬步千⾥,这次的基础打好了,以后的项⽬就⼿到擒来了。
地板和斜坡
第⼀个要做的,也是应该⽐较简单的,就是地板对象。3D中,地板应该是⼀个有些厚度、带上格⼦贴图的薄薄⽴⽅体平⾯。因此我对经过封装的⽴⽅体对象,⽤⼀段json对象定义如下:
{ name: '地板', type: 'cube', width: 1600, height: 10, depth: 1300, style: { 'm.color': '#BEC9BE', 'm.ambient': '#BEC9BE', } }
通过定义,创建了⼀个13⽶*16⽶的地板块,这也是客户⼩型机房的实际尺⼨:
html图片展示特效看起来有那么点意思,就是颜⾊还不够,需要⼀个地板砖纹理图。需要注意的是,纹理图的尺⼨都需要是宽和⾼都是2的幂,例如128x128、256*256等,这样出来效果才会好。这也是3D软件⼀般所要求的。另外纹理要能连续拼接不露破绽,这样才好。例如下⾯我google出来的图:
破绽,这样才好。例如下⾯我google出来的图:
在style⾥⾯添加:
'ure.image': 'images/floor.png', 'peat': new mono.Vec2(10,10),
效果如下:
有图⽚材质纹理,效果果然好多了。突然想到客户说,他们机房底⾯有⼀个⽅便运送设备的斜坡,必须要画出来。这……(╯-_-)╯
后来想到twaver⾥⾯的对象可以⽀持运算,⽐如可以定义⼀个斜的⽴⽅体,让地板剪掉⽴⽅体,就可以做到。于是继续定义json:
{ name:'地板切坡', type:'cube', width:200, height:20, depth:260, translate: [-348,0,530], rotate: [Math.PI/180*3, 0, 0], op:'-', style: { …, } }
这⾥定义的⼀个倾斜的⽴⽅体,通过translate定义位置,rotate定义旋转⾓度,然后再通过op定义运算符,这⾥是“减去”,就⽤“-”表⽰。被剪掉的⽴⽅体也可以设置材质、纹理、贴图、颜⾊…等等,和地板⼀样。看看效果:
第⼀步总算是有惊⽆险地搞定了。
⾛廊桌
下⼀步了个简单的对象,按要求⾛廊要放⼀个接待桌。为了简单,我决定就偷懒做⼀个⽴⽅体表⽰。
{ name: '⾛廊板凳', type: 'cube', width: 300, height: 50, depth: 100, translate: [350, 0, -500], }
效果如下:
这⾥偷懒其实是有原因的。在3D⾥,最重视的就是效率,千万不要放⼀些很复杂的模型,尤其是这类⾮业务对象。就像这个桌⼦,尽管只是个简单的⽴⽅体,但只要和整体风格协调⼀致,再增加⼀点配⾊并启动阴影效果后,看着就好多了:
墙体
墙体是机房⾥很重要的⼀个部分,有好的光照、阴影的效果才能看起来更加逼真。由于墙体是不规则的路径,⼀段⼀段去⽣成还真挺⿇烦的,还好引擎⽀持这种物体,甚⾄曲线路径都可以。这⾥只要在json⾥⾯定义⼀组数字的坐标,让这
些数字依次连接,组成⼀个墙体,最后⽣成3D对象放⼊场景中就⾏啦。
json定义如下:
{ name: '主墙体', type: 'path', width: 20, height: 200, translate: [-500, 0, -500], data:[ [0, 0], [1000, 0], [1000, 500], [500, 500], [500, 1000], [0, 1000], [0,0], ], }
注意这⾥的类型变成了path,data中定义了⼀个⼆维坐标数组来描述墙体。由于墙都是从底⾯开始的,所以只定义它的平⾯的x、y坐标就⾏了。看看效果:
不过如前⽂所说,还是需要上⾊、上阴影,才能有更好的效果。这⾥我们启⽤阴影并咨询设计师美眉⼏个颜⾊值,加上去后再看下效果:
以及⼀些细节:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论