如何使用WebGL实现空气高温热变形动画特效
我们在炎炎夏日,或者在火堆旁,经常会观察到热源周围空气的不稳定波动现象。
本文将讲解如何通过WebGL来实现这个特效。该效果可用于热变形、波浪、水面波光等场合。
首先让我们来看看如何能画出一个普通的图像,然后看看我们如何能使它变形。
使用WebGL绘制图像
在踏得网之前的教程中,我们已经说明过,WebGL可以通过纹理对象来加载外部图像文件并渲染。
本文略过初始化WebGL绘制上下文、着色器程序创建等基本步骤的描述,直接演示如何加载纹理贴图:
//基于image对象来创建纹理 function createTextureByImgObject(imgObj) { //设置当前激活纹理 webgl.activeTexture(webgl.TEXTURE0); //创建纹理对象,并设置其常用属性 var textureObject = webgl.createTexture(); webgl.bindTexture(webgl.TEXTURE_2D, textureObject); webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, imgObj); //使用最近像素来处理纹理缩放后的点 webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST); webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST); //使用边缘颜色来封装纹理,而不是左右两边的插值 webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE); webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE); return textureObject; } //从DOM中通过img标签的id来加载并创建纹理贴图 function createTextureByImgID(imgID) { var imgObj = document.getElementById(imgID); if (imgObj == null) { return null; } return createTextureByImgObject(imgObj); }
实现变形特效
正常情况下,我们的shader程序代码如下:
<script id="fsh_wave" type="x-shader/x-fragment"> precision mediump float; varying vec2 textureCoordinate; uniform sampler2D inputImageTexture; uniform float time; void main(){ vec4 color=texture2D(inputImageTexture,vec2(textureCoordinate.x, textureCoordinate.y)); gl_FragColor = color; } </script>
要想生成变形效果,我们可以调整textureCoordinate.x和y坐标映射值,具体而言,要产生竖向的波动变形,x得和y通过波动函数关联起来,常用的是正/余弦函数:
float frequency=100.0;//波动频率 float amp=0.003;//波动幅度 float distortion=sin(textureCoordinate.y*frequency)*amp; vec4 color=texture2D(inputImageTexture,vec2(textureCoordinate.x+distortion, textureCoordinate.y));
上面的代码只是实现一个静态的波动变形,接着我们要把这个波动变成动画,可以使用requestAnimationFrame方法,
同时设置一个随着动画帧而变的时间参数:
precision mediump float; varying vec2 textureCoordinate; uniform sampler2D inputImageTexture; uniform float time;//时间参数 void main(){ float frequency=100.0; float amp=0.003; float speed=0.05; float distortion=sin(textureCoordinate.y*frequency + time*speed)*amp; vec4 color=texture2D(inputImageTexture,vec2(textureCoordinate.x+distortion, textureCoordinate.y)); gl_FragColor = color; }
time的设置在动画绘制函数中:
function draw() { webgl.uniform1f(itv.time, time++); webgl.clearColor(0.0, 0.0, 0.0, 1.0); webgl.clear(webgl.COLOR_BUFFER_BIT); webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4); requestAnimationFrame(draw); } itv.time = webgl.getUniformLocation(programObject, "time"); draw();
你可以自己在线试试。
最新评论
- 相关文章
微信公众号在线生成二维码带参数怎么搞?
带参数二维码是微信公众号渠道二维码的一种实现
微信的带参数二维码有两种,一种是临时二维码,一种是永久二维码,但是永久二维码的生成是有个数限制的,微...2019年NodeJS框架Koa和Express选型比较
Koa和Express都是NodeJS的主流应用开发框架。
Express是一个完整的nodejs应用框架。Koa是由Express团队开发的,但是它有不同的关注点。Koa致力于核心中间件...Blender2.7给平面模型添加纹理贴图
在blender中给模型添加纹理,需要有2个步骤:首先在对象属性栏中给该对象添加材料和纹理建立纹理映射添加材料和纹理这是常见操作,略过步骤。但是仅仅这样操作,...
WebGL Roadmap
Unity 5.0 shipped with a working preview of our WebGL technology in March this year. Since then, Google has disabled (by default) NPAPI support in the...
CSS3弹性布局内容对齐(justify-content)属性使用详解
内容对齐(justify-content)属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线(main axis)对齐。该操作发生在弹性长度以及自动边距被确定后。 它用来在存...
Three.js入门教程1 - 基础知识和创建一个红色球体
[ TECHBROOD注:Three.js是一个主流的开源WebGL库,WebGL允许使用JavaScript直接操作GPU,在网页上实现3D效果。
Google的工程师Paul在网站aerotwist.com上...WebGL入门教程5 - 详解纹理滤镜(Texture Filter)
WebGL中使用纹理贴图来实现细腻的物体表面观感,其中一个重要的参数是纹理滤镜(Texture Filter)。
这个参数用来处理当对象出现缩放时,纹理如何处理中间...如何实现SVG clipPath自适应被裁剪对象
CSS3中引入的clip-path(裁剪路径)属性是一个很强大的特性。
clip-path的含义如下图所示,好比剪纸一样,你用剪刀沿着某条路径把目标对象(图像或元素)裁...WebGL入门教程4 - 使用纹理贴图(Texture Map)
3D建模和纹理贴图的关系就好比人体和皮肤(或着装)的关系,3D建模用来处理空间属性,而贴图适合用来处理细腻的表面属性。如果不使用贴图,而想在表面达到足够的...
如何基于Canvas来模拟真实雨景Part2:重力掉落和雨滴融合
D3.js读取外部json数据
D3.js是一个很好的数据可视化工具,支持从web服务读取json数据,或者从外部文件如.json, .csv文件中直接读取。由于部分服务比如flickrs上的图文数据服务需要VPN...
更多...