这是我之前在项目中写的一个shader特效。
github地址 github.com/songshujitu…
js代码渲染流程如下
var gl = canvas.getContext('webgl',{antialias:true,alpha: true,premultipliedAlpha: true});
if(!gl) return;
//USE gl.UNSIGNED_INT
var ext = gl.getExtension('OES_element_index_uint');
gl.viewport(0, 0, glcanvas.width, glcanvas.height);
gl.enable(gl.DEPTH_TEST);
gl.clearStencil(gl.STENCIL_BUFFER_BIT);
gl.clearColor(0,0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.blendEquation(gl.FUNC_ADD);
// gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
var shader = shaderPrograme(gl,vs,fs);
gl.useProgram(shader.program);
var program = shader.program;
var aPosition = gl.getAttribLocation(program, "aPosition");
var aNormal = gl.getAttribLocation(program, "aNormal");
var aUV = gl.getAttribLocation(program, "aUV");
var uResolution = gl.getUniformLocation(program, "uResolution");
var uSize = gl.getUniformLocation(program, "uSize");
var uTime = gl.getUniformLocation(program, "uTime");
var uxTime = gl.getUniformLocation(program, "uxTime");
var plane = Plane({width:88 * 2,height:88 * 2,pivot:{x:0.5,y:0.5}});
var buffers = plane[0];
var indices = plane[1];
var rawBuffer = gl.createBuffer();
var buffferTypedata = new Float32Array(buffers);
gl.bindBuffer(gl.ARRAY_BUFFER, rawBuffer);
gl.bufferData(gl.ARRAY_BUFFER,buffferTypedata , gl.STATIC_DRAW);
var indexBuffer = gl.createBuffer();
indexBuffer.numItems = indices.length;
indexBuffer.typeArray = new Uint16Array(indices);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexBuffer.typeArray,gl.STATIC_DRAW)
gl.bindBuffer(gl.ARRAY_BUFFER, rawBuffer);
gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 8 * buffferTypedata.BYTES_PER_ELEMENT, 0 * buffferTypedata.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(aPosition);
gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 8 * buffferTypedata.BYTES_PER_ELEMENT, 3 * buffferTypedata.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(aNormal);
gl.vertexAttribPointer(aUV, 2, gl.FLOAT, false,8 * buffferTypedata.BYTES_PER_ELEMENT, 6 * buffferTypedata.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(aUV);
...
gl.uniform4fv(uTime,[time,time,time,time]);
gl.uniform4fv(uxTime,[time,time,time,time]);
gl.drawElements(gl.TRIANGLES, indexBuffer.numItems, gl.UNSIGNED_SHORT,0);
glsl代码如下
attribute vec3 aPosition;
attribute vec3 aNormal;
attribute vec2 aUV;
uniform vec2 uResolution;
uniform vec2 uSize;
uniform vec4 uxTime;
varying vec2 vUV;
varying vec3 vNormal;
void main() {
vec2 zeroToOne = aPosition.xy / uResolution;
vec2 clipSpace = zeroToOne * 2.0 - 1.0;
vec4 pos = vec4(clipSpace * vec2(1, -1), 0, 1);
gl_Position = pos;
vUV = aUV * 2.0 - 1.0;
vUV.x = vUV.x + 0.02 * sin(uxTime.y);
vUV.y = vUV.y + 0.01 * sin(uxTime.y);
vNormal = aNormal;
}
precision mediump float;
uniform sampler2D iChannel0; //root
uniform sampler2D iChannel1; //ball
uniform sampler2D iChannel2; //flow
uniform sampler2D iChannel3; //remap
uniform sampler2D iChannel4; //plante
uniform sampler2D iChannel5; //ballflowmask
uniform sampler2D iChannel6; //kanji
//uniform sampler2D iChannel7; //glowBall
uniform vec4 uTime;
varying vec2 vUV;
varying vec3 vNormal;
vec2 rotate(vec2 uv, vec4 param,float time){
float cosx = cos(param.z + param.w * time);
float sinx = sin(param.z + param.w * time);
mat2 m2 = mat2(cosx, sinx, -sinx, cosx);
return m2 * (uv.xy - param.xy) + param.xy;
}
vec2 minmax(vec2 uv){
return vec2(uv.x > 0. ?( mod(uv.x,(1.+0.))) : (1.+0.) - mod(abs(uv.x),(1.+0.)),
uv.y > 0. ?( mod(uv.y,(1.+0.))) : (1.+0.) - mod(abs(uv.y),(1.+0.)));
}
bool discard_uv(vec2 uv,vec2 uv_orign){
bool discard_uv = false;
if(uv.x > 1. || uv.y > 1.)
discard_uv = true;
if(uv_orign.x < 0.)
discard_uv = true;
if(uv_orign.x > 1.)
discard_uv = true;
if(uv_orign.y < 0.)
discard_uv = true;
if(uv_orign.y > 1.)
discard_uv = true;
return discard_uv;
}
void main() {
vec2 uv = vUV;
vec4 rootcolor = texture2D(iChannel0,uv);
vec2 uv_remap4 = uv;
float uv_remap4A = texture2D(iChannel3,uv_remap4).b * texture2D(iChannel3,uv_remap4).a;
vec4 color_remap4 = texture2D(iChannel3,uv_remap4);
if(color_remap4.b >= 0.5)
color_remap4 = vec4(0.,color_remap4.gba);
vec4 mask1color = texture2D(iChannel4,uv);
color_remap4.a = color_remap4.a * mask1color.a;
vec2 plantebguv = uv;
plantebguv = color_remap4.rg;
plantebguv = plantebguv-vec2(0.5,0.5);
plantebguv = plantebguv+vec2(-0.3486328,0.006835938) * uTime.y ;
plantebguv = plantebguv+vec2(0.5,0.5);
vec2 oringuv = plantebguv;
plantebguv = minmax(oringuv);
bool discard_plantuv = false;
if(plantebguv.x > 1. || plantebguv.y > 1.)
discard_plantuv = true;
// vec4 color_plantebg = texture2D(iChannel7,plantebguv);
//if(discard_plantuv == true) color_plantebg = vec4(0.,0.,0.,0.);
//color_plantebg = vec4(color_plantebg.rgb,color_plantebg.a * color_remap4.a);
vec4 result = vec4(0.0); //
vec2 flowuv = uv;
flowuv -= vec2(0.5);
flowuv += vec2(0.03515625,-0.0009765625);
flowuv += vec2(0.005859375,-0.2929688) * uTime.y;
flowuv /= vec2(1.162582,1.19222);
flowuv += vec2(0.5);
vec2 oringflowuvuv = flowuv;
flowuv = minmax(oringflowuvuv);
bool discard_flowuv = false;
if(flowuv.x > 1. || flowuv.y > 1.)
discard_flowuv = true;
vec4 flowcolor = texture2D(iChannel2,flowuv);
vec4 ballmask = texture2D(iChannel5,uv);
flowcolor = vec4(flowcolor.rgb * flowcolor.a * ballmask.r,1.0);
vec2 flowcoloruv = -(flowcolor.r*vec2(-0.02929688,0.046875) + flowcolor.g*vec2(0.07617188,0.02734375) + flowcolor.b*vec2(0.,0.) + flowcolor.a*vec2(0.,0.));
vec2 balluv = uv;
balluv -= vec2(0.5);
balluv = balluv+vec2(0.01464844,0.06347668);
balluv = balluv/vec2(0.8144531,0.8554688);
balluv += vec2(0.5);
vec2 balluv_orign = balluv + flowcoloruv;
balluv = minmax(balluv_orign);
bool discard_balluv = discard_uv(balluv,balluv_orign);
vec4 ballcolor = texture2D(iChannel1,balluv);
if(discard_balluv == true) ballcolor = vec4(0.);
vec2 kanjiuv = uv;
kanjiuv -= vec2(0.5);
kanjiuv = kanjiuv+vec2(0.02050781,0.02246094);
kanjiuv = kanjiuv/vec2(0.5507813,0.5507813);
kanjiuv += vec2(0.5);
kanjiuv.x = kanjiuv.x + sin(uTime.y) * 0.04;
vec2 kanjiuv_orign = kanjiuv;
kanjiuv = minmax(kanjiuv_orign);
bool discard_kanjiuv = discard_uv(kanjiuv,kanjiuv_orign);
vec4 kanjicolor = texture2D(iChannel6,kanjiuv);
if(discard_kanjiuv == true) kanjicolor = vec4(0.);
result = mix(result,vec4(rootcolor.rgb * 1.0,1.) ,rootcolor.a);
result = mix(result,vec4( ballcolor.rgb,1.) , ballcolor.a);
result = mix(result,vec4(mask1color.rgb ,1.) ,mask1color.a);
result = mix(result,vec4(kanjicolor.rgb * 1.0,1.) ,kanjicolor.a);
gl_FragColor = result;
}