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

如何重新命名,以便在需要时仅将画布内容上载到纹理

  •  1
  • gman  · 技术社区  · 7 年前

    如何阻止a frame上传每帧的画布纹理?

    我在初始化时只设置了一次此画布,但检查调用 texImage2D 它正在不断上传。

    const elem = document.querySelector("#ui span");
    let count = 0;
    WebGLRenderingContext.prototype.texImage2D = (function(origFn) {
      return function(...args) {
        elem.textContent = [++count, ...args].join(' ');
        origFn.call(this, ...args);
      };
    }(WebGLRenderingContext.prototype.texImage2D));
    #ui {
      position: fixed;
      left: 0;
      top: 0;
      z-index: 1000;
      background: gray;
      color: white;
      padding: .5em;
    }
    <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
    <script>
    AFRAME.registerComponent('draw-canvas-once', {
      schema: {type: 'selector'},
    
      init: function () {
        const canvas = this.canvas = this.data;
        const ctx = this.ctx = canvas.getContext('2d');
        ctx.fillStyle = '#F00';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.font = "70px sans-serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillStyle = "#000";
        ctx.fillText("X", 150, 75);
      },
    });
    </script>
    <a-scene>
      <a-assets>
        <canvas id="helloWorldCanvas" crossOrigin="anonymous"></canvas>
      </a-assets>
    
      <a-entity material="shader: flat; src: #helloWorldCanvas"
                geometry="primitive: plane; width: 160; height: 90"
                position="0 60 -250" rotation="0 35 0"
                draw-canvas-once="#helloWorldCanvas">
      </a-entity>
    </a-scene>
    <div id="ui">texImage2D call count: <span></span></div>

    你也可以比较一下性能。这里有一架100架飞机和100幅油画。在我的MPB上,它以每秒20帧的速度运行

    const elem = document.querySelector("#ui span");
    let then = 0;
    function check(now) {
      const et = now - then;
      then = now;
      elem.textContent = (1 / (et * 0.001)).toFixed(2);
      requestAnimationFrame(check);
    }
    requestAnimationFrame(check);
    πu{
    位置:固定;
    左:0;
    顶部:0;
    Z-指数:1000;
    背景:灰色;
    颜色:白色;
    衬垫:.5em;
    }
    <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
    <script>
    AFRAME.registerComponent('grid', {
      schema: {
        across: {type: 'int', default: 3},
        down: {type: 'int', default: 3},
      },
      init() {
        for (let y = 0; y < this.data.down; ++y) {
          for (let x = 0; x < this.data.across; ++x) {
            const id = `c${x}${y}`;
            const elem = document.createElement('a-entity');
            elem.setAttribute('draw-canvas-once', {id});
            elem.setAttribute('geometry', { 
               primitive: 'plane', 
               height: 1, 
               width: 1,
             });
            elem.setAttribute('material', {
              shader: 'flat', src: `#${id}`,
            });
            this.el.appendChild(elem);
            elem.setAttribute('position', {
              x: (x - this.data.across / 2) * 1.1, 
              y: (y - this.data.down / 2) * 1.1, 
              z: 0,
            });
          }
        }
      },
    });
    AFRAME.registerComponent('draw-canvas-once', {
      schema: {id: {type: 'string'}},
      init() {
        const canvas = this.canvas = document.createElement('canvas');
        document.body.appendChild(canvas);
        canvas.id = this.data.id;
        const ctx = this.ctx = canvas.getContext('2d');
        ctx.fillStyle = '#F00';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.font = "70px sans-serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillStyle = "#000";
        ctx.fillText(this.data.id, 150, 75);
      },
    });
    </script>
    <a-scene>
      <a-assets>
      </a-assets>
      <a-entity grid="across: 10; down: 10" position="0 0 -10" />
    </a-scene>
    <div id="ui">fps: <span></span></div>

    对比100架飞机,没有画布,只是一幅图像。它以每秒60帧的速度运行。两个样本应以相同的速度运行。

    const elem=document.queryselector(“ui-span”);
    设为0;
    功能检查(现在){
    const et=现在-然后;
    那么=现在;
    elem.textcontent=(1/(et*0.001)).tofixed(2);
    请求动画框架(选中);
    }
    请求动画框架(选中);
    πu{
    位置:固定;
    左:0;
    顶部:0;
    Z-指数:1000;
    背景:灰色;
    颜色:白色;
    衬垫:.5em;
    }
    <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
    <script>
    AFRAME.registerComponent('grid', {
      schema: {
        across: {type: 'int', default: 3},
        down: {type: 'int', default: 3},
      },
      init() {
        for (let y = 0; y < this.data.down; ++y) {
          for (let x = 0; x < this.data.across; ++x) {
            const elem = document.createElement('a-entity');
            elem.setAttribute('geometry', { 
               primitive: 'plane', 
               height: 1, 
               width: 1,
             });
            elem.setAttribute('material', {
              shader: 'flat', src: '#img',
            });
            this.el.appendChild(elem);
            elem.setAttribute('position', {
              x: (x - this.data.across / 2) * 1.1, 
              y: (y - this.data.down / 2) * 1.1, 
              z: 0,
            });
          }
        }
      },
    });
    </script>
    <a-scene>
      <a-assets>
        <img id="img" src="https://i.imgur.com/ZKMnXce.png" crossorigin="anonymous" />
      </a-assets>
      <a-entity grid="across: 10; down: 10" position="0 0 -10" />
    </a-scene>
    <div id="ui">fps: <span></span></div>
    1 回复  |  直到 7 年前
        1
  •  2
  •   ngokevin    7 年前

    A-frame正在做:

    loadCanvas: function (src, data, cb) {
      // Hack readyState and HAVE_CURRENT_DATA on canvas to work with THREE.VideoTexture
      src.readyState = 2;
      src.HAVE_CURRENT_DATA = 2;
      this.loadVideo(src, data, cb);
    },
    

    合并公关时出现错误,将得到修复。

    同时,您可以手动创建一个3.js canvastexture,并将其分配给组件中的材质。