大家好,今天我ccentry要做一个水波纹特效,我们来看看水波纹特效的做法。首先我们来看一下水波纹特效的效果是怎么样的,请看下图。

我们要做的就是类似这种纹理特效,那么我们来看看是如何制作的吧。首先鲫鱼我新建一个空项目,来编写这个demo,项目结构如下图所示。

img文件夹中存放的是uv贴图和底图,js文件夹下存放的是jquery和我的水波纹效果的js文件,还有就是展示页面index.html。很简单,没什么东西了,接下来就来看鲫鱼我是怎么实现上面这个水波纹特效的吧。我们先开始编辑ripples.js,这就是这个特效的核心功能。再来看一遍工程结构。

且看鲫鱼我怎么写这个ripple.js。首先我们检查浏览器是否支持webgl的api,这是一个浏览器校验功能函数,代码块如下。
var gl; function hasWebGLSupport() { var canvas = document.createElement('canvas'); var context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); var result = context && context.getExtension('OES_texture_float') && context.getExtension('OES_texture_float_linear'); return result; }
这里先是创建了一个canvas标签,然后由这个canvas中拿到context('webgl')对象,我们所有做webgl的api都由此而来。这里只是校验并获取gl对象的动作,然后我们来看函数的返回值,这里有个js的&&运算符的妙用,result = context && context.getExtension('OES_texture_float') && context.getExtension('OES_texture_float_linear');这句话是指context存在,就取context.getExtension('OES_texture_float'),而且context.getExtension('OES_texture_float')存在,就取context.getExtension('OES_texture_float_linear'),这是递进式的取值方式,我们最终通过了前两个的校验获取到了'OES_texture_float_linear'对象,鲫鱼相信大家也都看得懂,我们就不在这里浪费时间了,继续往下看。
var supportsWebGL = hasWebGLSupport();这句就一目了然了,我们调用了hasWebGLSupport函数,从而获取到了'OES_texture_float_linear'线性浮点数的材质处理对象。这个对象我们后面要使用到,现在这里拿到手再说。我们接下去看。
function createProgram(vertexSource, fragmentSource, uniformValues) { function compileSource(type, source) { var shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { throw new Error('compile error: ' + gl.getShaderInfoLog(shader)); } return shader; } var program = {}; program.id = gl.createProgram(); gl.attachShader(program.id, compileSource(gl.VERTEX_SHADER, vertexSource)); gl.attachShader(program.id, compileSource(gl.FRAGMENT_SHADER, fragmentSource)); gl.linkProgram(program.id); if (!gl.getProgramParameter(program.id, gl.LINK_STATUS)) { throw new Error('link error: ' + gl.getProgramInfoLog(program.id)); } // Fetch the uniform and attribute locations program.uniforms = {}; program.locations = {}; gl.useProgram(program.id); gl.enableVertexAttribArray(0); var name, type, regex = /uniform (\w+) (\w+)/g, shaderCode = vertexSource + fragmentSource; while ((match = regex.exec(shaderCode)) != null) { name = match[2]; program.locations[name] = gl.getUniformLocation(program.id, name); } return program; }
这一个功能自然不必再解释了,这是gl对象绑定shader的工具,参数为vertexSource顶点着色器字符串,fragmentSource片段着色器字符串,uniformValues向着色器传递的参数,如果读者对这个函数存在疑问,鲫鱼建议读者先学习《webgl编程指南》和阅读鲫鱼之前的博客https://www.cnblogs.com/ccentry/p/9864847.html,这里不再赘述。我们再往下看。
function bindTexture(texture, unit) { gl.activeTexture(gl.TEXTURE0 + (unit || 0)); gl.bindTexture(gl.TEXTURE_2D, texture); }

