项目中写的一个shader特效

150 阅读2分钟

这是我之前在项目中写的一个shader特效。

GIF 2021-4-28 18-26-10.gif

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;
    }