如何使用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();
你可以自己在线试试。
最新评论
- 相关文章
3D感知和建模关键硬件技术:双目、3D结构光和TOF
无论VR、AR和3D打印,其核心技术包含3D成像和建模。而3D建模属于劳动密集型的工作,耗时耗力,凡这类工作都会是被新技术革命的地方,自动3D建模技术就是为了解决...
CSS3属性选择器特性使用详解
CSS3除了引入动画、滤镜(用于特效)以及新的布局技术外,在选择器(selector)方面也有增强。属性选择器根据元素的属性(attributes)来匹配。这可以是一个单独...
前端开发框架技术选型:Angular2 VS React VS jQuery
Angular和React是主流的2个前端开发框架,但是严格来说两者并非对等的概念。Angular是一个基于MVC(或者MVVM)的框架,包含model(模型)/view(视图)/controll...
CSS3弹性布局弹性流(flex-flow)属性详解和实例
弹性布局是CSS3引入的强大的布局方式,用来替代以前Web开发人员使用的一些复杂而易错hacks方法(如使用float进行类似流式布局)。其中flex-flow是flex-direction...
HTML5、Hybrid APP、Native APP对比和技术选型
HTML5和Native APP都很容易理解。为了获得HTML5的移植性和移动本地应用的高性能,搞出来一些混合APP的解决方案。比如Apache的Cordova(也就是以前的PhoneGap),...
深入理解Three.js(WebGL)贴图(纹理映射)和UV映射
本文将详细描述如何使用Three.js给3D对象添加贴图(Texture Map,也译作纹理映射,“贴图”的翻译要更直观,而“纹理映射”更准确。)。为了能够查看在线演示效...
如何使用Three.js加载obj和mtl文件
OBJ和MTL是3D模型的几何模型文件和材料文件。在最新的three.js版本(r78)中,以前的OBJMTLLoader类已废弃。现在要加载OBJ和MTL文件,需要结合OBJLoader和MTLLoade...
WebVR简介和常用资源链接
什么是WebVR这是一个实验性的JavaScript API,提供了在用户网页浏览器中访问虚拟现实设备的统一接口。当前主流VR设备如Oculus Rift DK2、谷歌的CardBoard、三星...
如何使用WebGL创建一个逼真的下雨动画
之前写过文章来分别讲解如何使用CSS3和Canvas2D实现过雨滴和下雨动画。通过背景处理看起来也有视觉上的3D效果,但并非真正的3D场景,如果要加入用户交互,进行36...
浏览器控制台报JS脚本执行错误:Module is not defined
现在JS分成了两个分支,一部分在服务器端发展如NodeJS,一部分是传统的浏览器运行环境。
有些插件在编写JS代码时,是针对Node编写的,所以直接在浏览器中使...WebGL入门教程1 - 3D绘图基础知识
现代浏览器努力使得Web用户体验更为丰富,而WebGL正处于这样的技术生态系统的中心位置。其应用范围覆盖在线游戏、大数据可视化、计算机辅助设计、虚拟现实以及数...
Processing.js和P5.js的功能简介和区别
什么是ProcessingProcessing是关于数字艺术的编程语言,支持跨平台,语言本身是一个类Java语言,程序文件的后缀为.pde。
什么是Processing.js为了能让Proce...在PHP网页程序中执行Sass/Compass命令
我们需要在wow云开发平台支持sass/compass等预编译样式语言,为此我们首先尝试了scssphp扩展,但是在支持最新语法上,经常会出现异常。所以我们采用了代理的方式...
更多...