Shadertoy代码转成Threejs ShaderPass注意点

在这里插入图片描述
上图是来自ShaderToy的下雪效果 与 自己加的小球融合。
思路
1、 把ShaderToy的代码转成自定义ShaderMaterial
2、把ShaderMaterial作为参数构建一个ShaderPass

注意点:
1、ShaderToy与自己的模型的融合
比如ShaderToy最后输出的gl_FragColor是

vec3 color_1 = vec3(Snowout*0.9, Snowout, Snowout*1.1);
gl_FragColor = vec4(color_1, 1.0);

要与自己的模型融合 应该定义一个 sampler2D类型的 tDiffuse 变量,通过uniforms传入。mix融合后的代码

 vec4 texel = texture2D( tDiffuse, vUv );
    vec3 color_1 = vec3(Snowout*0.9, Snowout, Snowout*1.1);
    gl_FragColor = vec4(mix(color_1, texel.rgb, 0.5), 1.0);

2、 要定义一个ClearPass加入通道,否则,更新模型后之前的画面不会清除。

关键代码展示

composer = new EffectComposer( renderer );
  clearPass = new ClearPass( params.clearColor, params.clearAlpha );
  composer.addPass( clearPass );

  texturePass = new TexturePass();
  // composer.addPass( texturePass );
  const textureLoader = new THREE.TextureLoader();
  textureLoader.load( "hardwood2_diffuse.jpg", function ( map ) {
    texturePass.map = map;
  } );

  renderPass = new RenderPass( scene, cameraP );
  renderPass.renderToScreen = true
  renderPass.clear = false;
  composer.addPass( renderPass );

  let vertexShader = `
		varying vec2 vUv;
		void main(){
			vUv = uv;
			gl_Position = projectionMatrix  * vec4(position, 1.0);
		}
	`;
  let fragmentShader = `
// This shader useds noise shaders by stegu -- http://webstaff.itn.liu.se/~stegu/
  // This is supposed to look like snow falling, for example like http://24.media.tumblr.com/tumblr_mdhvqrK2EJ1rcru73o1_500.gif

uniform vec3      iResolution;           // 视口分辨率(像素)
  uniform float     iTime;
  varying vec2 vUv;
  uniform vec2 iMouse;
  uniform sampler2D tDiffuse;

  vec2 mod289(vec2 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
  }

  vec3 mod289(vec3 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
  }

  vec4 mod289(vec4 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
  }

  vec3 permute(vec3 x) {
    return mod289(((x*34.0)+1.0)*x);
  }

  vec4 permute(vec4 x) {
    return mod((34.0 * x + 1.0) * x, 289.0);
  }

  vec4 taylorInvSqrt(vec4 r)
  {
    return 1.79284291400159 - 0.85373472095314 * r;
  }

  float snoise(vec2 v)
  {
    const vec4 C = vec4(0.211324865405187,0.366025403784439,-0.577350269189626,0.024390243902439);
    vec2 i  = floor(v + dot(v, C.yy) );
    vec2 x0 = v -   i + dot(i, C.xx);

    vec2 i1;
    i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
    vec4 x12 = x0.xyxy + C.xxzz;
    x12.xy -= i1;

    i = mod289(i); // Avoid truncation effects in permutation
    vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
      + i.x + vec3(0.0, i1.x, 1.0 ));

    vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
    m = m*m ;
    m = m*m ;

    vec3 x = 2.0 * fract(p * C.www) - 1.0;
    vec3 h = abs(x) - 0.5;
    vec3 ox = floor(x + 0.5);
    vec3 a0 = x - ox;

    m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );

    vec3 g;
    g.x  = a0.x  * x0.x  + h.x  * x0.y;
    g.yz = a0.yz * x12.xz + h.yz * x12.yw;

    return 130.0 * dot(m, g);
  }

  float cellular2x2(vec2 P)
  {
    #define K 0.142857142857 // 1/7
    #define K2 0.0714285714285 // K/2
    #define jitter 0.8 // jitter 1.0 makes F1 wrong more often

    vec2 Pi = mod(floor(P), 289.0);
    vec2 Pf = fract(P);
    vec4 Pfx = Pf.x + vec4(-0.5, -1.5, -0.5, -1.5);
    vec4 Pfy = Pf.y + vec4(-0.5, -0.5, -1.5, -1.5);
    vec4 p = permute(Pi.x + vec4(0.0, 1.0, 0.0, 1.0));
    p = permute(p + Pi.y + vec4(0.0, 0.0, 1.0, 1.0));
    vec4 ox = mod(p, 7.0)*K+K2;
    vec4 oy = mod(floor(p*K),7.0)*K+K2;
    vec4 dx = Pfx + jitter*ox;
    vec4 dy = Pfy + jitter*oy;
    vec4 d = dx * dx + dy * dy; // d11, d12, d21 and d22, squared
    // Sort out the two smallest distances

    // Cheat and pick only F1
    d.xy = min(d.xy, d.zw);
    d.x = min(d.x, d.y);
    return d.x; // F1 duplicated, F2 not computed
  }

  float fbm(vec2 p) {
    float f = 0.0;
    float w = 0.5;
    for (int i = 0; i < 5; i ++) {
      f += w * snoise(p);
      p *= 2.;
      w *= 0.5;
    }
    return f;
  }

  void main( )
  {
    float speed=2.0;

    vec2 uv = vUv.xy / iResolution.xy;

    uv.x*=(iResolution.x/iResolution.y);

    vec2 suncent=vec2(0.3,0.9);

    float suns=(1.0-distance(uv,suncent));
    suns=clamp(0.2+suns,0.0,1.0);
    float sunsh=smoothstep(0.85,0.95,suns);

    float slope;
    slope=0.8+uv.x-(uv.y*2.3);
    slope=1.0-smoothstep(0.55,0.0,slope);

    float noise=abs(fbm(uv*1.5));
    slope=(noise*0.2)+(slope-((1.0-noise)*slope*0.1))*0.6;
    slope=clamp(slope,0.0,1.0);

    vec2 GA;
    GA.x-=iTime*1.8;
    GA.y+=iTime*0.9;
    GA*=speed;

    float F1=0.0,F2=0.0,F3=0.0,F4=0.0,F5=0.0,N1=0.0,N2=0.0,N3=0.0,N4=0.0,N5=0.0;
    float A=0.0,A1=0.0,A2=0.0,A3=0.0,A4=0.0,A5=0.0;


    // Attentuation
    A = (uv.x-(uv.y*0.3));
    A = clamp(A,0.0,1.0);

    // Snow layers, somewhat like an fbm with worley layers.
    F1 = 1.0-cellular2x2((uv+(GA*0.1))*8.0);
    A1 = 1.0-(A*1.0);
    N1 = smoothstep(0.998,1.0,F1)*1.0*A1;

    F2 = 1.0-cellular2x2((uv+(GA*0.2))*6.0);
    A2 = 1.0-(A*0.8);
    N2 = smoothstep(0.995,1.0,F2)*0.85*A2;

    F3 = 1.0-cellular2x2((uv+(GA*0.4))*4.0);
    A3 = 1.0-(A*0.6);
    N3 = smoothstep(0.99,1.0,F3)*0.65*A3;

    F4 = 1.0-cellular2x2((uv+(GA*0.6))*3.0);
    A4 = 1.0-(A*1.0);
    N4 = smoothstep(0.98,1.0,F4)*0.4*A4;

    F5 = 1.0-cellular2x2((uv+(GA))*1.2);
    A5 = 1.0-(A*1.0);
    N5 = smoothstep(0.98,1.0,F5)*0.25*A5;

    float Snowout=N5+N4+N3+N2+N1;

    Snowout = 0.35+(slope*(suns+0.3))+(sunsh*0.6)+N1+N2+N3+N4+N5;
    vec4 texel = texture2D( tDiffuse, vUv );
    vec3 color_1 = vec3(Snowout*0.9, Snowout, Snowout*1.1);
    gl_FragColor = vec4(mix(color_1, texel.rgb, 0.5), 1.0);
  }
  `
  let myShader = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader,
    side: THREE.DoubleSide,
    transparent: true,
    uniforms: {
      iTime: timeValue,
      iResolution: {value: new THREE.Vector2(1, 1)},
      iMouse: iMouseValue,
      'tDiffuse': { value: null }
    },
  })
  let myPass = new ShaderPass(myShader)
  composer.addPass( myPass );

  scene.add(new THREE.AxesHelper(500))

  const copyPass = new ShaderPass( CopyShader );
  copyPass.clear = true
  composer.addPass( copyPass );
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值