Nicolas
Nicolas

Reputation: 2281

partial texture update in three.js

I upload a large texture to my fragment shader as a map in three.js.

This texture is a 2D canvas on which I draw random shapes.

While drawing, I just want to update the part of the texture that has changed. Updating the whole texture (up to 3000x3000 pixel) is just too slow.

However, I can not get to perform a partial update. texSubImage2D doesn't have any effect in my scene.

No errors in the console - I expect that I am missing a step but can not figure it out yet.

//
// create drawing canvas 2D and related textures
//

this._canvas = document.createElement('canvas');
this._canvas.width = maxSliceDimensionsX;
this._canvas.height = maxSliceDimensionsY;

this._canvasContext = this._canvas.getContext('2d')!;
this._canvasContext.fillStyle = 'rgba(0, 0, 0, 0)';
this._canvasContext.fillRect(0, 0, window.innerWidth, window.innerHeight);

this._texture = new Texture(this._canvas);
this._texture.magFilter = NearestFilter;
this._texture.minFilter = NearestFilter;

// const data = new Uint8Array(maxSliceDimensionsX * maxSliceDimensionsY * 4);
// this._texture2 = new THREE.DataTexture(data, maxSliceDimensionsX, maxSliceDimensionsY, THREE.RGBAFormat);

this._brushMaterial = new MeshBasicMaterial({
  map: this._texture,
  side: DoubleSide,
  transparent: true,
});
...


// in the render loop
renderLoop() {
   ...
   // grab random values as a test
   const imageData = this._canvasContext.getImageData(100, 100, 200, 200);
   const uint8Array = new Uint8Array(imageData.data.buffer);

   // activate texture?
   renderer.setTexture2D(this._texture, 0 );
   // update subtexture
   const context = renderer.getContext();
   context.texSubImage2D( context.TEXTURE_2D, 0, 0, 0, 200, 200, context.RGBA, context.UNSIGNED_BYTE, uint8Array);

   // updating the whole texture works as expected but is slow
   // this._texture.needsUpdate = true;

    // Render new scene
    renderer.render(scene, this._camera);

}

Thanks, Nicolas

Upvotes: 0

Views: 971

Answers (1)

Nicolas
Nicolas

Reputation: 2281

Right after creating the texture, we must notify three that the texture needs to be uploaded to the GPU.

We just have to set it 1 time at creation time and not in the render loop.

this._texture = new Texture(this._canvas);
this._texture.magFilter = NearestFilter;
this._texture.minFilter = NearestFilter;

// MUST BE ADDED
this._texture.needsUpdate = true;

Upvotes: 2

Related Questions