8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

three.jsのCanvasTextureで透明の境界部分にアーティファクトが生じる問題の対処方法

Posted at

three.jsで背景が透明なcanvasからCanvasTextureを作成したときに、canavs内のオブジェクトと透明な背景の境界部分にエッジ上のアーティファクトが生じる場合の対処方法です。

具体例として以下のようなコードを見ていきます。このコードではCanvas 2Dで透明な背景に白色で四角形と文字をcanvasに描き、そのcanvasからCanvasTextureを生成して平面のメッシュに張り付けています。マテリアルのtransparenttrueにしているので、Cavnas 2Dで透明にしている部分はthree.jsの背景色に設定している薄紫色が見えるようになっています。

const width = 640;
const height = 480;
const scene = new THREE.Scene();
scene.background = new THREE.Color('rgb(240, 230, 255)');
const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 100);
camera.position.z = 2.0;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

const canvas2d = document.createElement('canvas');
canvas2d.width = 512;
canvas2d.height = 512;
const context2d = canvas2d.getContext('2d');
context2d.fillStyle = 'rgb(255, 255, 255)';
context2d.fillRect(10, 10, 400, 130);
context2d.fillRect(200, 400, 250, 70);
context2d.font = '100px sans-serif';
context2d.fillText('Hello', 10, 250);
context2d.fillText('World!', 120, 340);

const texture = new THREE.CanvasTexture(canvas2d);

const geometry = new THREE.PlaneBufferGeometry();
const material = new THREE.MeshBasicMaterial({
  map: texture,
  transparent: true,
  depthWrite: false,
});
scene.add(new THREE.Mesh(geometry, material));

renderer.render(scene, camera);

このコードの描画結果は以下のようになり、Canvas 2Dで描いたオブジェクト(四角形と文字)と背景の境界部分に灰色のエッジが生じています。
alpha-edge01.png

なぜこのようなアーティファクトが生じるかというと、canvasはPremultiplied Alphaという形式で取得されるにも関わらず通常のテクスチャと同じように使用しているためのようです。

対処方法としては、CanvasTextureをPremultiplied Alphaと認識されるようにして、マテリアルのアルファブレンディングの設定をそれに合わせたものにします。具体的には次のように設定するとよさそうです。

const texture = ...
texture.premultiplyAlpha = true;

const material = ...
material.blending = THREE.CustomBlending;
material.blendSrc = THREE.OneFactor;
material.blendDst = THREE.OneMinusSrcAlphaFactor;
material.blendEquation = THREE.AddEquation;   

このように設定したときの描画結果は次のようになり、境界部分のアーティファクトが消えていることが確認できました。
alpha-edge02.png

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?