纯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实现烟雾的粒子系统效果等等,但元旦假期结束了我明天还要上班,其他可完善的地方留给读者去想象了。

纯Shading Language绘制飞机火焰效果的更多相关文章
- 纯Shading Language绘制HTML5时钟
今天是2014年的最后一天,这个时刻总会让人想起时钟,再过几个小时地球人都要再老了一岁,于是搞个HTML5版的时钟就是我们今天要完成的任务,实现HTML5的时钟绘制一般会采用三种方式,第一种采用CSS ...
- canvas绘制“飞机大战”小游戏,真香!
canvas是ArkUI开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活.高效等优点,被广泛应用于UI界面开发中. 本期,我们将为大家介绍canvas组件的使用. 一.canvas介绍 1 ...
- [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第3讲(逻辑方法的实现)
整体展示: 上一讲实现了诸多对象,这次我们就需要实现许多逻辑方法,如控制飞机移动,判断子弹击中敌机,敌机与英雄飞机相撞等等.并且我们在实现这些功能的时候需要计时器去调用这些方法.setInterval ...
- [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第2讲(对象的实现及全局变量的定义)
整体展示: 一.全局变量 /*===================玩家参数==========================*/ var myPlane; //英雄对象 var leftbtn = ...
- [知了堂学习笔记]_纯JS制作《飞机大战》游戏_第1讲(实现思路与游戏界面的实现)
整体效果展示: 一.实现思路 如图,这是我完成该项目的一个逻辑图,也是一个功能模块完成的顺序图. 游戏界面的完成 英雄飞机对象实现,在实现发射子弹方法过程中,又引出了子弹对象并实现.在此时,英雄飞机能 ...
- OpenGL ES 3.0之Shading Language(八)
每个OpenGL ES 3.0程序要求一个顶点着色器和一个片段着色器去渲染一个图形.着色器概念是API 的中心,本篇将介绍着色器语言部分包含下面几项 1.变量和变量类型 2.矢量和矩阵创建及选择 3. ...
- 前端每日实战:156# 视频演示如何用纯 CSS 创作一个飞机舷窗风格的 toggle 控件
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/jeaOrw 可交互视频 此视频是可 ...
- OpenGL ES Shading Language中应尽量避免使用循环
In addition to basic if-then-else statements, it is possible to write for, while, and do-while loo ...
- (OpenGL ES 2.0 Shading Language) attribute 、uniform 和 varying
一:attribute .uniform 和 varying 都是glsl的变量的内存指示器(storage qualifiers),指明变量的内存特性 二:attribute attribute 是 ...
随机推荐
- google搜索技巧汇总
由于不能访问google,可访问ggso.in进行搜索. 简单整理记录一下常用的一些Google搜索技巧:或操作一般搜索时,如果输入多个词,默认是与的关系,如输入词1和词2,即搜索同时包含词1和词2的 ...
- Http规范
1. 关于 HTTP Basic Authentication http://blog.itpub.net/23071790/viewspace-709367/ 通过以下代码,提示用户登录 Respo ...
- 浅谈Excel开发:八 Excel 项目的安装部署
前面几篇文章讲解了Excel开发的几个比较主要的也是比较重要的方面,比如菜单系统,Excel对象模型,自定义函数,RTD函数,异步自定义函数,用户自定义任务面板等,在实际开发中我们还会遇到各种“千奇百 ...
- 浅谈Excel开发:五 Excel RTD函数
上文介绍了Excel中的UDF函数,本文介绍一下同样重要的RTD函数.从Excel 2002开始,Excel引入了一种新的查看和更新实时数据的机制,即real-time data简称RTD函数 ...
- 自动备份文件到GITHUB的方法
由于一个制作着玩的项目需要制作上传文件的功能,自己又不是搞网站的,也不想去维护一个服务器. 于是开发了一个上传服务器,可以自动把我上传到服务器的数据同步到Github服务器 而github服务器又提供 ...
- 换个角度理解云计算之HDFS
学习云计算,必然得了解Hadoop,而Hadoop中的HDFS(分布式文件系统)是一个基础,接下来就写一下我所理解的HDFS. 有一个很有特别的村庄,村庄里面有一个很牛逼的人,叫做“大哥”,村民们都信 ...
- Qt QT_BEGIN_NAMESPACE
问题 阅读Qt的Demo源码的时候,经常在头文件中, 声明类型的部分有以下这样的代码: class MyClassA; ///< 自定义类的声明 QT_BEGIN_NAMESPACE class ...
- Http基础
Http基础 这篇文章是讲Android网络请求的先导文章,主要讲Http工作流程,请求报文和响应报文的格式,以及GET和POST方法的具体含义. Http工作流程 HTTP是一个客户端和服务器端请求 ...
- webservice5
如何访问webservice . 三种方式我知道, 但是, 方式1 只说明了如何访问wsdl, 不知道如何调用,现在就是需要知道如何像下面url描述一样 , http get .post 方式调用ws ...
- Kafka入门初探+伪集群部署
Kafka是目前非常流行的消息队列中间件,常用于做普通的消息队列.网站的活性数据分析(PV.流量.点击量等).日志的搜集(对接大数据存储引擎做离线分析). 全部内容来自网络,可信度有待考证!如有问题, ...