如何获取框架只在需要时将画布内容上传到纹理

时间:2018-05-23 16:55:50

标签: aframe

如何停止帧画每帧上传画布纹理?

我只是在初始设置此画布一次,但检查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>
&#13;
&#13;
&#13;

您也可以只比较性能。这是一架有100架飞机和100幅画布的飞机。在我的MPB上,它运行速度为20fps

&#13;
&#13;
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);
&#13;
#ui {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 1000;
  background: gray;
  color: white;
  padding: .5em;
}
&#13;
<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>
&#13;
&#13;
&#13;

vs 100 plane没有画布,只是一个图像。它以60fps运行。两个样品应以相同的速度运行。

&#13;
&#13;
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);
&#13;
#ui {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 1000;
  background: gray;
  color: white;
  padding: .5em;
}
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

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);
},

合并PR时糟糕的滑倒,将会解决。

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