纯shader实现圆圈内缓缓上升的波浪线(three.js实战10)

纯shader实现圆圈内缓缓上升的波浪线

1. demo效果

小球波浪效果

2. RawShaderMaterial介绍

我们之前在three.js中使用着色器,大多时候都是通过ShaderMaterial着色器材质传入着色器程序,使用这个着色器材质比较方便,因为three.js已经内置了很多常用的变量如position、color、normal、uv等,其实three.js还提供了另外一个着色器材质RawShaderMaterial,与ShaderMaterial相比唯一的区别就是去掉了上面提到的内置变量,需要什么变量完全自己定义,这一次就使用这个材质完全定义自己需要的变量编写着色器程序

3. demo代码

demo代码量较少,就不一一说明了,请直接查阅代码

<body>
  <div id="container"></div>
  <script type="text/javascript" src="../three/build/three.js"></script>

  <script>
    var container;
    var camera, scene, planeMesh, renderer;
    var uniforms = {
    
    
      u_resolution: {
    
    
        type: "v2",
        value: new THREE.Vector2()
      },
      radius: {
    
    
        type: "f",
        value: 0.5
      },
      u_time: {
    
    
        type: "f",
        value: 0.5
      }
    };
    var vertexShader = `
    attribute vec3 position;
    void main() {
      gl_Position = vec4( position, 1.0 );
    }
    `
    var fragmentShader = `
    #ifdef GL_ES
    precision mediump float;
    #endif
    uniform vec2 u_resolution;
    uniform float u_time;
    uniform float radius;

    
    void main( void ) {
      vec2 uv = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;
      vec2 center = vec2(.0,.0);
      float dist = distance(center,uv);

      float angularVelocity = 12.0;//角速度
      float frequency = 12.0;//频率
      float amplitude = 0.05;//振幅
      float offset = -0.5;//偏距
      float initialPhase = frequency * u_time;//初相位
      float y = amplitude * sin((angularVelocity*uv.x)+initialPhase)+offset;//波浪函数
 
      if(y < 1.0){
        y += u_time/10.0;
      }
      if(dist < radius){//在圆内
        if(uv.y < y){//波浪以下部分着色
          gl_FragColor = vec4(0.1,0.6,0.9,1.0);
        }else{
          gl_FragColor = vec4(0.1,0.2,0.3,.6);
        }
      }
   
        
    }
    `

    init();
    animate();

    function init() {
    
    
      container = document.getElementById('container');

      camera = new THREE.Camera();

      scene = new THREE.Scene();


      var geometry = new THREE.PlaneBufferGeometry(2, 2);

      var material = new THREE.RawShaderMaterial({
    
    
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader
      });

      planeMesh = new THREE.Mesh(geometry, material);


      scene.add(planeMesh);


      renderer = new THREE.WebGLRenderer();
      renderer.setSize(800, 800); //设置窗口大小800px*800px

      container.appendChild(renderer.domElement);
      uniforms.u_resolution.value.x = renderer.domElement.width;
      uniforms.u_resolution.value.y = renderer.domElement.height;

    }


    function animate() {
    
    
      requestAnimationFrame(animate);

      planeMesh.material.uniforms.u_time.value += 0.02;
      if (planeMesh.material.uniforms.u_time.value > 10.0) {
    
    
        planeMesh.material.uniforms.u_time.value = 0.0
      }

      renderer.render(scene, camera);
    }
  </script>
</body>

猜你喜欢

转载自blog.csdn.net/qw8704149/article/details/118583852
今日推荐