Shadertoy 多个buffers 转成Threejs代码

转载来源

如题:

将Shadertoy 多个buffers 转成Threejs代码

比如 https://www.shadertoy.com/view/4sG3WV
在这里插入图片描述
转成Threejs的代码

// Port from Shadertoy to THREE.js: https://www.shadertoy.com/view/4sG3WV

const VERTEX_SHADER = `
    varying vec2 vUv;
    
    void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }
`;

const BUFFER_A_FRAG = `
    uniform vec4 iMouse;
    uniform sampler2D iChannel0;
    uniform sampler2D iChannel1;
    uniform vec2 iResolution;
    uniform float iFrame;
    varying vec2 vUv;
    
    #define mousedata(a,b) texture2D( iChannel1, (0.5+vec2(a,b)) / iResolution.xy, -0.0 )
    #define backbuffer(uv) texture2D( iChannel0, uv ).xy
    
    float lineDist(vec2 p, vec2 start, vec2 end, float width) {
        vec2 dir = start - end;
        float lngth = length(dir);
        dir /= lngth;
        vec2 proj = max(0.0, min(lngth, dot((start - p), dir))) * dir;
        return length( (start - p) - proj ) - (width / 2.0);
    }
    
    void main() {
        vec2 uv = vUv;
        vec2 col = uv;
        if (iFrame > 2.) {
            col = texture2D(iChannel0,uv).xy;
            vec2 mouse = iMouse.xy/iResolution.xy;
            vec2 p_mouse = mousedata(2.,0.).xy;
            if (mousedata(4.,0.).x > 0.) {
                col = backbuffer(uv+((p_mouse-mouse)*clamp(1.-(lineDist(uv,mouse,p_mouse,0.)*20.),0.,1.)*.7));
            }
        }
        gl_FragColor = vec4(col,0.0,1.0);
    }

`;

const BUFFER_B_FRAG = `
    uniform vec4 iMouse;
    uniform sampler2D iChannel0;
    uniform vec3 iResolution;
    varying vec2 vUv;
    
    bool pixelAt(vec2 coord, float a, float b) {
        return (floor(coord.x) == a && floor(coord.y) == b);
    }
    
    vec4 backbuffer(float a,float b) {
      return texture2D( iChannel0, (0.5+vec2(a,b)) / iResolution.xy, -100.0 );
    }
    
    void main( ) {
    
        vec2 uv = vUv;// / iResolution.xy;
        vec4 color = texture2D(iChannel0,uv);
    
        if (pixelAt(gl_FragCoord.xy,0.,0.)) { //Surface position
            gl_FragColor = vec4(backbuffer(0.,0.).rg+(backbuffer(4.,0.).r*(backbuffer(2.,0.).rg-backbuffer(1.,0.).rg)),0.,1.);
        } else if (pixelAt(gl_FragCoord.xy,1.,0.)) { //New mouse position
            gl_FragColor = vec4(iMouse.xy/iResolution.xy,0.,1.);
        } else if (pixelAt(gl_FragCoord.xy,2.,0.)) { //Old mouse position
            gl_FragColor = vec4(backbuffer(1.,0.).rg,0.,1.);
        } else if (pixelAt(gl_FragCoord.xy,3.,0.)) { //New mouse holded
            gl_FragColor = vec4(clamp(iMouse.z,0.,1.),0.,0.,1.);
        } else if (pixelAt(gl_FragCoord.xy,4.,0.)) { //Old mouse holded
            gl_FragColor = vec4(backbuffer(3.,0.).r,0.,0.,1.);
        } else {
            gl_FragColor = vec4(0.,0.,0.,1.);
        }
    
    }
`;

const BUFFER_FINAL_FRAG = `
    uniform sampler2D iChannel0;
    uniform sampler2D iChannel1;
    varying vec2 vUv;
    
    void main() {
        vec2 uv = vUv;
        vec2 a = texture2D(iChannel1,uv).xy;
        gl_FragColor = vec4(texture2D(iChannel0,a).rgb,1.0);
    }
`;

class App {

  constructor() {

    this.width = 1024;
    this.height = 512;

    this.renderer = new THREE.WebGLRenderer();
    this.loader = new THREE.TextureLoader();
    this.mousePosition = new THREE.Vector4();
    this.orthoCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
    this.counter = 0;

    this.renderer.setSize(this.width, this.height);
    document.body.appendChild(this.renderer.domElement);

    this.renderer.domElement.addEventListener('mousedown', () => {
      this.mousePosition.setZ(1);
      this.counter = 0;
    });

    this.renderer.domElement.addEventListener('mouseup', () => {
      this.mousePosition.setZ(0);
    });

    this.renderer.domElement.addEventListener('mousemove', event => {
      this.mousePosition.setX(event.clientX);
      this.mousePosition.setY(this.height - event.clientY);
    });

    this.targetA = new BufferManager(this.renderer, {
      width: this.width,
      height: this.height
    });
    this.targetB = new BufferManager(this.renderer, {
      width: this.width,
      height: this.height
    });
    this.targetC = new BufferManager(this.renderer, {
      width: this.width,
      height: this.height
    });

  }


  start() {

    const resolution = new THREE.Vector3(this.width, this.height, window.devicePixelRatio);
    const channel0 = this.loader.load('https://res.cloudinary.com/di4jisedp/image/upload/v1523722553/wallpaper.jpg');
    this.loader.setCrossOrigin('');

    this.bufferA = new BufferShader(BUFFER_A_FRAG, {
      iFrame: {
        value: 0
      },
      iResolution: {
        value: resolution
      },
      iMouse: {
        value: this.mousePosition
      },
      iChannel0: {
        value: null
      },
      iChannel1: {
        value: null
      }
    });

    this.bufferB = new BufferShader(BUFFER_B_FRAG, {
      iFrame: {
        value: 0
      },
      iResolution: {
        value: resolution
      },
      iMouse: {
        value: this.mousePosition
      },
      iChannel0: {
        value: null
      }
    });

    this.bufferImage = new BufferShader(BUFFER_FINAL_FRAG, {
      iResolution: {
        value: resolution
      },
      iMouse: {
        value: this.mousePosition
      },
      iChannel0: {
        value: channel0
      },
      iChannel1: {
        value: null
      }
    });

    this.animate();

  }

  animate() {
    requestAnimationFrame(() => {

      this.bufferA.uniforms['iFrame'].value = this.counter++;

      this.bufferA.uniforms['iChannel0'].value = this.targetA.readBuffer.texture;
      this.bufferA.uniforms['iChannel1'].value = this.targetB.readBuffer.texture;
      this.targetA.render(this.bufferA.scene, this.orthoCamera);

      this.bufferB.uniforms['iChannel0'].value = this.targetB.readBuffer.texture;
      this.targetB.render(this.bufferB.scene, this.orthoCamera);

      this.bufferImage.uniforms['iChannel1'].value = this.targetA.readBuffer.texture;
      this.targetC.render(this.bufferImage.scene, this.orthoCamera, true);

      this.animate();

    });

  }

}

class BufferShader {

  constructor(fragmentShader, uniforms = {}) {

    this.uniforms = uniforms;
    this.material = new THREE.ShaderMaterial({
      fragmentShader: fragmentShader,
      vertexShader: VERTEX_SHADER,
      uniforms: uniforms
    });
    this.scene = new THREE.Scene();
    this.scene.add(
      new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), this.material)
    );
  }

}

class BufferManager {


  constructor(renderer, size) {

    this.renderer = renderer;

    this.readBuffer = new THREE.WebGLRenderTarget(size.width, size.height, {
      minFilter: THREE.LinearFilter,
      magFilter: THREE.LinearFilter,
      format: THREE.RGBAFormat,
      type: THREE.FloatType,
      stencilBuffer: false
    });

    this.writeBuffer = this.readBuffer.clone();

  }

  swap() {
    const temp = this.readBuffer;
    this.readBuffer = this.writeBuffer;
    this.writeBuffer = temp;
  }

  render(scene, camera, toScreen = false) {
    if (toScreen) {
      this.renderer.render(scene, camera);
    } else {
      this.renderer.setRenderTarget(this.writeBuffer);
      this.renderer.clear();
      this.renderer.render(scene, camera)
      this.renderer.setRenderTarget(null);
    }
    this.swap();
  }

}

document.addEventListener('DOMContentLoaded', () => {
  (new App()).start();
});
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值