如何使用WebGL实现空气高温热变形动画特效

techbrood 发表于 2016-06-09 21:51:31

标签: webgl, heat, distortion

- +

我们在炎炎夏日,或者在火堆旁,经常会观察到热源周围空气的不稳定波动现象。

本文将讲解如何通过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));

blob.png

上面的代码只是实现一个静态的波动变形,接着我们要把这个波动变成动画,可以使用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();

你可以自己在线试试

possitive(17) views17989 comments0

发送私信

最新评论

请先 登录 再评论.
相关文章
  • 常用光照类型基本概念工作原理及其计算公式

    在三维场景中,原理上物体的渲染效果取决于光照与物体表面的相互作用,对于渲染程序而言,可以通过把一些数学公式应用于像素着色来实现,从而模拟出真实生活中的...

  • CSS3属性选择器特性使用详解

    CSS3除了引入动画、滤镜(用于特效)以及新的布局技术外,在选择器(selector)方面也有增强。属性选择器根据元素的属性(attributes)来匹配。这可以是一个单独...

  • 如何使用CSS3合成模式(blend-mode)和滤镜(filter)实现彩色蜡笔(时光机)照片特效

    在之前的文章中我们已经详细讲解过CSS3滤镜(filter,也可称之为过滤器)的工作方式,本文将实现一个当下流行的时光机相片特效实例来说明其实际用途。
    我们...

  • 深入理解CSS3滤镜(filter)功能和实例详解

    CSS3滤镜功能源自SVG滤镜规范,SVG滤镜最早用来给矢量图添加类似PS中像素图的一些特效。
    把这个滤镜功能引入到普通HTML元素中可以带来很有趣的效果(模糊、...

  • HTTP1.1协议现状、问题和解决方案

    HTTP的现状最早的HTTP协议非常简单,只能用来传送文本,方法也只有GET,后来逐步发展到1.1,能够支持多种MIME格式数据(如文本、文件),支持GET,POST,HEAD,OPTI...

  • 学习使用CSS制作进度条

    进度条是基础的界面控件,可用于多种场合,比如任务完成进度,手机充电状态等。本文介绍一个简单实用的进度条制作方法。预期效果如下图所示:直观上,我们可以把该进度条控件分为2个部分,外部的边界用来表示固定的目标范围,里面的条形部分用来表示当前进度。外部目标范围元素的CSS代码编写如下:.pb-scope

  • Blender2.7 快捷键一览表

    通用操作
    停止当前操作:ESC
    快捷搜索:SPACE撤销:ctrl+z重做:ctrl+shift+z渲染:F12
    单选:鼠标右键(RMB)全选:A
    框选:B
    刷选:...

  • Three.js入门教程4 - 创建粒子系统动画

    嗨,又见面了。这么说我们已经开始学习Three.js了,如果你还没有看过之前三篇教程,建议你先读完。如果你已经读完前面的教程了,你可能会想做一些关于粒子的东西。让我们直面这个话题吧,每个人都爱粒子效果。不管你是否知道,你可以很轻易地创建它们。

  • 如何使用WebGL创建一个逼真的下雨动画

    之前写过文章来分别讲解如何使用CSS3和Canvas2D实现过雨滴和下雨动画。通过背景处理看起来也有视觉上的3D效果,但并非真正的3D场景,如果要加入用户交互,进行36...

  • 浏览器控制台报JS脚本执行错误:Module is not defined

    现在JS分成了两个分支,一部分在服务器端发展如NodeJS,一部分是传统的浏览器运行环境。
    有些插件在编写JS代码时,是针对Node编写的,所以直接在浏览器中使...

  • 如何基于Canvas来模拟真实雨景Part1:预备知识和创建基本对象

    我们之前使用CSS3实现过

  • D3.js读取外部json数据

    D3.js是一个很好的数据可视化工具,支持从web服务读取json数据,或者从外部文件如.json, .csv文件中直接读取。由于部分服务比如flickrs上的图文数据服务需要VPN...

  • 使用纯CSS3实现一个3D旋转的书本

    有一些前沿的电商网站已经开始使用3D模型来展示商品并支持在线定制,而其中图书的展示是最为简单的一种,无需复杂的建模过程,使用图片和CSS3的一些变换即可实现...

  • 更多...