纯Shading Language绘制飞机火焰效果

上篇《纯Shading Language绘制HTML5时钟》体现了GLSL可编程性特点,但没有体现GLSL可编程出各种酷炫效果的特点,今天我们将用纯Shading Language绘制火焰效果,并将其应用到《HT图形组件设计之道(四)》飞行的飞机例子上。

火焰的例子我已发在 http://js.do/hightopo/fireball,其本质在绘制gl.POINTS的点类型时,通过在Fragment Shader在点区域内生成noise的噪声用于绘制多种颜色效果,并将多次不同噪声算法生成的颜色进行叠加,同时噪声的生成还依赖于time的时间参数,这样最终融合成不错的圆形火焰效果。

采用gl.POINTS的绘制方式会受不同浏览器对点大小的限制,可通过gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)获知浏览器支持的最小和最大范围,一般也都有1~255或1~300的区间,所以也基本够用于展示效果,http://js.do/hightopo/fireball的例子中52行中的float color = 3.0 – (3.*length(2.*p));其中的第一个3.0是火焰强度intensity参数,可通过改变此值达到改变火焰强度的效果,可在1.0~4.0范围体验从小火到大火的调节效果。

HT图形组件设计之道(四)》文中的例子我将在飞机的尾部叠加该火焰效果,由于考虑到自定义GLSL的复杂性,HT并未开放图元自定义GLSL的功能,我们将要采用的是在Graph3dView的上层再次叠加一个WebGL驱动的Canvas,火焰是绘制到这个上层的Canvas,因此和HT的Graph3dView完全是松耦合,不会影响HT的3D组件自身的所有显示和交互功能,这样的应用有点类似《百度地图与HT for Web结合的GIS网络拓扑应用》中GIS地图与HT的GraphView组件叠加效果。

当然这样叠加会导致火焰始终在最上层,无法真实反映三维空间层次的问题,但作为监控系统应用最关键的是展示重要指标,例如对于电信网管应用,当设备有告警冒泡呈现时,往往要求告警冒泡要呈现在最上层不要被其他设备遮挡住,同样如果真的飞机失火需要监控系统实时提示该告警信息时,肯定也是需要该火焰不被遮挡,因此真实世界的层次瑕疵在这里反而是合适的解决方案。

叠加Canvas到Graph3dView比较容易,通过Graph3dView.getView().appendChild(canvas)加入,并在Graph3dView布局时同时布局Cavnas位置大小,火焰的位置我们是这样实现的,将一个隐藏的node节点host到飞机的尾部,这样该节点会自定跟随飞机飞行过程的位置变化,绘制时火焰时我们通过Graph3dView#toViewPosition函数将node三维坐标转换成二维的屏幕Cavnas的坐标,这还没完我们还得将屏幕坐标转换成WebGL驱动的Canvas的POINT点坐标,相关代码如下:

function draw(){
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(0.0, 0.0, 0.0, 0.0);
    gl.clear(gl.COLOR_BUFFER_BIT);     

    gl.uniform1f(gl.getUniformLocation(program, 'time'), (Date.now() - startTime)/1000 ); 
    gl.uniform1f(gl.getUniformLocation(program, 'intensity'), intensity ); 

    var vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

    var position = g3d.toViewPosition(node.p3());                                
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
         position.x/g3d.getWidth()*2 - 1,
         1 - position.y/g3d.getHeight()*2
    ]), gl.STATIC_DRAW);
    var vertexLocation = gl.getAttribLocation(program, "aVertexPosition");
    gl.vertexAttribPointer(vertexLocation, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertexLocation);                   
    gl.drawArrays(gl.POINTS, 0, 1);

    requestAnimationFrame(draw); 
}              

function resizeCanvas(){
    canvas.width = g3d.getWidth() * devicePixelRatio;
    canvas.style.width = g3d.getWidth() + 'px';  
    canvas.height = g3d.getHeight() * devicePixelRatio;
    canvas.style.height = g3d.getHeight() + 'px';                 
}

以上代码我们还传入了intensity的强度参数,该参数我们通过ht.Default.startAnim动画函数,控制其值在0~4之间不断来回变化,这样可达到火焰有小变大来回变换的类似告警闪烁提示效果。还有var devicePixelRatio = window.devicePixelRatio;参数也是容易被忽略的细节,该值会根据设备的retina支持程度有不同的值,避免在高分辨率设备下出现锯齿模糊的问题,当然通过devicePixelRatio增大canvas.width和canvas.height也是有内存绘制性能代价的,如果效果要求不是太高情况下也可以都采用1来处理,其实要求不太高的三维场景即使时retina为3的iphone 6强制用devicePixelRatio为1的方式也不会有太大问题,并且能节省内存提高绘制性能,某些低性能的终端某些情况下甚至可以再降级到小于1的值以牺牲效果换取性能。

千辛万苦终于让飞机飞出了我想要的效果(http://v.youku.com/v_show/id_XODYyMzU3MDg0.html),当然还有无数的细节可以完善,例如可以根据飞机离eye的距离动态改变POINT点的大小,或改造GLSL实现烟雾的粒子系统效果等等,但元旦假期结束了我明天还要上班,其他可完善的地方留给读者去想象了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逍遥剑客的游戏开发

一些VR渲染优化方法

2208
来自专栏知识分享

红外接收控制灯亮灭

先上图 功能 红外接收头接收到红外信号,控制一个灯翻转 ? 使用74HC123是因为红外接收头接收的是一连串的高低电平,,在接收到第一个电平的跳变沿的时候就控制...

2776
来自专栏生信技能树

用了旧的CNV芯片还用旧的参考基因组,把数据发出来也不容易啊

Published online 2017 Mar 16. doi: 10.1186/s13058-017-0825-6

943
来自专栏Coding迪斯尼

对Box2D的物理世界进行图像美化和关卡选择设计

我们用Box2D绘制了很多几何图形,例如圆形,矩形,复杂一点就是两个矩形交叉的合在一起,中间再加个圆形。显然这种界面“太素”了,一个丰富多彩,五彩斑斓的游戏世界...

551
来自专栏前端杂货铺

使用canvas截图或者改变灰度

简述 html5新添加的canvas API可以让我们对画布进行开发应用,典型的是可以使用canvas截图或者 手工绘制“迷你图”(即嵌入在文本中的高清小图片)...

3348
来自专栏Linux驱动

裸机LCD驱动配置

本节来学习裸机下的LCD 驱动,本节学完后,再来学习Linux下如何使用LCD驱动 Linux中的LCD驱动,链接如下: (Linux-LCD层次分析链接:ht...

1758
来自专栏阮一峰的网络日志

资源描述框架RDF

在图书馆里,每一本书都要被编目,这样才能方便查找和利用。于是,很早就有人想到,网上所有的资源也需要"编目"。 如果要对网络资源编目,首先就必须有一套"编目规则"...

3377
来自专栏Python中文社区

数据挖掘实战(一):Kaggle竞赛经典案例剖析

專 欄 ❈那只猫,Python中文社区专栏作者,Python中文社区新Logo设计者,现就读于英国剑桥大学。 ❈— Load Lib ? 在这边提一下为什么要...

2407
来自专栏施炯的IoT开发专栏

GSM Communication on EBox4300--(2)

  上一篇GSM Communication on EBox4300--(1)主要是关于EBox4300上实现GSM通信的框架。这次就讲讲如何设计包含西门子TC...

1919
来自专栏HenCoder

Android 开发进阶: 自定义 View 1-1 绘制基础

从今天开始,HenCoder 就正式开讲知识技能了。按照我的计划,第一季是 UI,UI 一共分为三部分:绘制、布局和触摸反馈。本期是绘制部分的第一期。绘制大概会...

732

扫码关注云+社区