代码之家  ›  专栏  ›  技术社区  ›  Niraj

具有threejs材质的着色器在帧中不工作

  •  0
  • Niraj  · 技术社区  · 7 年前

    我试图通过自定义着色器为组件内创建的实体添加波,但添加着色器后场景立即消失。如果移除着色器,实体将显示为静态实体。

    这是一个密码笔: codepen

        <script>
      AFRAME.registerComponent('waves', {
      init: function() {
        var texture = new THREE.TextureLoader().load( "https://cinemont.com/tutorials/zelda/water.png" );
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(5, 5);
      this.geometry = new THREE.PlaneBufferGeometry( 4000, 2000, 128, 64 ); 
      this.material = new THREE.MeshPhongMaterial({
       map:texture,
       color: 0xffffff,
       opacity: 1,
       blending: THREE.NoBlending,
       side: THREE.DoubleSide,
       transparent: false,
       depthTest: false,
       wireframe: false 
      });
        var plane = new THREE.Mesh(this.geometry, this.material);
        plane.position.set(0, -400, -300);
        plane.rotation.set(Math.PI / 2, 0, 0);
        var el = this.el;
        el.setObject3D('mesh', plane);
      }
    });
    </script>
    <script>
    AFRAME.registerShader('makewaves', {
      schema: {
        color: {type: 'color', is: 'uniform', default: '#0051da'},
        timeMsec: {type: 'time', is: 'uniform'}
      },
    
      vertexShader: `
    #define SCALE 10.0
    
    varying vec2 vUv;
    
    uniform float timeMsec;  
    
    float calculateSurface(float x, float z) {
        float uTime = timeMsec / 1000.0;
        float y = 0.0;
        y += (sin(x * 1.0 / SCALE + uTime * 1.0) + sin(x * 2.3 / SCALE + uTime * 1.5) + sin(x * 3.3 / SCALE + uTime * 0.4)) / 3.0;
        y += (sin(z * 0.2 / SCALE + uTime * 1.8) + sin(z * 1.8 / SCALE + uTime * 1.8) + sin(z * 2.8 / SCALE + uTime * 0.8)) / 3.0;
        return y;
    }
    
    void main() {
        float uTime = timeMsec / 1000.0;
        vUv = uv;
        vec3 pos = position;    
        float strength = 1.0;
        pos.y += strength * calculateSurface(pos.x, pos.z);
        pos.y -= strength * calculateSurface(0.0, 0.0);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
    }  
    `,
      fragmentShader: `
    varying vec2 vUv;
    
    uniform sampler2D uMap;
    
    uniform vec3 color;
    
    uniform float timeMsec; 
    
    void main() {
        float uTime = timeMsec / 1000.0;     
        vec2 uv = vUv * 10.0 + vec2(uTime * -0.05);
    
        uv.y += 0.01 * (sin(uv.x * 3.5 + uTime * 0.35) + sin(uv.x * 4.8 + uTime * 1.05) + sin(uv.x * 7.3 + uTime * 0.45)) / 3.0;
        uv.x += 0.12 * (sin(uv.y * 4.0 + uTime * 0.5) + sin(uv.y * 6.8 + uTime * 0.75) + sin(uv.y * 11.3 + uTime * 0.2)) / 3.0;
        uv.y += 0.12 * (sin(uv.x * 4.2 + uTime * 0.64) + sin(uv.x * 6.3 + uTime * 1.65) + sin(uv.x * 8.2 + uTime * 0.45)) / 3.0;
    
        vec4 tex1 = texture2D(uMap, uv * 1.0);
        vec4 tex2 = texture2D(uMap, uv * 1.0 + vec2(0.2));
    
        vec3 blue = color;
    
        gl_FragColor = vec4(blue + vec3(tex1.a * 0.9 - tex2.a * 0.02), 1.0);
    
    }`
    });
    </script>
    <a-scene>
            <a-camera postion="0 1.2 0"></a-camera>     
      <a-entity material="shader:makewaves;" 
                waves></a-entity>
      <a-entity light="type: directional; color: #ffffff; intensity: 2.8; castShadow:true;" position="0 2 -10"></a-entity>
      <a-light type="point" color="blue" position="0 5 0"></a-light>
        <a-light type="directional" color="blue" intensity="1.8" position="0 5 0"></a-light> 
    </a-scene>
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Piotr Adam Milewski    7 年前

    这里的问题是,应用材质中的明暗器不提供贴图均匀/纹理值。

    另一方面,您尝试两次创建材质:

    a-frame s material 成分
    waves 人字架 处理大部分的问题,或者完全在THREE.js中创建网格(geometry+material)。

    框架
    这里没什么要补充的。您的着色器不会为纹理暴露任何统一,因此在 registerShader 您需要将其添加到架构中:

    AFRAME.registerShader('makewaves', {
      schema: {
         ......,
        uMap: {
          type: 'map',
          is: 'uniform'
        }
      }, .....
    

    <a-plane postion="1 1.2 2" width="5" height="5" rotation="-90 0 90" material="shader:makewaves; 
    uMap: https://cinemont.com/tutorials/zelda/water.png;"></a-plane>
    

    那么 人字架 将使用vertexShader和fragmentShader创建新的着色器。 例子 here .


    此外,基于@ngokvin的anwser,向默认平面添加更多的线段将允许更多的顶点随着“wave”运动而移动。
    segments-height="20" segments-width="20"
    

    here .


    THREE.ShaderMaterial :

    THREE.ShaderMaterial({
         fragmentShader: this.fragmentShader, // custom fragment shader
         vertexShader: this.vertexShader, // custom vertex shader
         ......
    

    过来看 here .

        2
  •  0
  •   ngokevin    7 年前

    你还需要 segments-height="20" segments-width="20" a-plane 给它顶点置换。默认平面仅在角上有顶点,因此不会得到波浪。

    https://codepen.io/anon/pen/MPoBKz?editors=1000