如何使用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) views18145 comments0

发送私信

最新评论

请先 登录 再评论.
相关文章
  • CentOS6 Apache2.2多站点HTTPS配置

    可以使用letsencrypt(certbot)免费证书服务。支持多系统、多站点和多目录,支持wildcard(通配符域名),90天生效,可用定时任务自动更新。需要注意一点的是apache2.4以下版本需要在默认的ssl配置中添加如下的指令:NameVirtualHost

  • 3D感知和建模关键硬件技术:双目、3D结构光和TOF

    无论VR、AR和3D打印,其核心技术包含3D成像和建模。而3D建模属于劳动密集型的工作,耗时耗力,凡这类工作都会是被新技术革命的地方,自动3D建模技术就是为了解决...

  • Monaco Editor 编辑器拷贝粘贴功能调用和获取选中文本

    有时候需要在monaco editor外部调用编辑器的内置功能比如希望在页面主工具栏实现一些快捷操作。button

  • WebAssembly工作原理和JavaScript语言性能对比分析

    本文简单说明WebAssembly(简称wasm)工作原理和高性能的原由(和JavaScript相比)。不过需要提醒的是Wasm并非设计来完全替代JS,而是对JS的一个强大补充,JS中...

  • JavaScript事件模型图解

    在JavaScript中用户交互的核心部分就是事件处理。本文为对事件模型和处理机制的总体性描述。Event是什么?
    event是用户操作网页时发生的交互动作,比如clic...

  • Three.js 对象局部坐标转换为世界坐标

    在Three.js中进行顶点几何计算时,一个需要注意的地方是,需要统一坐标系。比如你通过Three.js提供的API创建了一个球体网孔对象,那么默认情况下,各网孔顶点的...

  • 如何使用Three.js加载obj和mtl文件

    OBJ和MTL是3D模型的几何模型文件和材料文件。在最新的three.js版本(r78)中,以前的OBJMTLLoader类已废弃。现在要加载OBJ和MTL文件,需要结合OBJLoader和MTLLoade...

  • Three.js入门教程6 - 创建全景图和纹理

    全景图非常酷。使用Three.js做一个属于自己的全景图并不是那么困难。要做一个全景图,你需要一个软件用来做一张全景图片。我使用了iPhone上的Microsoft Photosyn...

  • Three.js 开发基础知识 - 绘制3D对象

    Three.js是一个用来简化WebGL开发的JavaScript库,比如绘制一个三维立方体,使用WebGL需要100多行,那Three.js只要10几行就能够完成。本文通过创建一个立方体来...

  • inline-block元素设置overflow:hidden属性导致相邻行内元素向下偏移

    在表单修改界面中常会使用一个标签、一个内容加一个修改按钮来组成单行界面,如图1所示。那么在表单总长度受限的情况下,当中间的邮箱名称过长时,会遮盖到旁边...

  • 如何使用纯CSS3实现一个3D泡沫

    要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble

  • 更多...