みかづきブログ・カスタム

基本的にはちょちょいのほいです。

A-Frameで深度をつかってマスクを掛ける 👀

f:id:kimizuka:20201130222254j:plain

A-Frameは内部でThree.jsを使っているので、

Three.Material.colorWriteをfalseにすることで、実現できます。

threejs.org

.colorWrite : Boolean

Whether to render the material's color. This can be used in conjunction with a mesh's renderOrder property to create invisible objects that occlude other objects. Default is true.

https://threejs.org/docs/index.html#api/en/materials/Material.colorWrite より引用

マテリアルの色をレンダリングするかどうか。これをメッシュのrenderOrderプロパティと組み合わせて使用​​すると、他のオブジェクトを遮る非表示のオブジェクトを作成できます。デフォルトはtrueです。

Google翻訳にて翻訳

百聞は一件にしかずなので試してみましょう。

DEMO

<a-scene
  vr-mode-ui="enabled: false"
>
  <a-plane
    plane
    color="blue"
    width="99"
    height="1.2"
    position="0 -1 -5"
  ></a-plane>
  <a-box
    mask
    color="red"
    position="0 -1 -6"
    rotation="0 45 0"
    width="1.2"
    height="1.2"
    depth="1.2"
  ></a-box>
</a-scene>

こんな感じで、planeとboxを置くと、

f:id:kimizuka:20210106000524p:plain

planeの裏にboxを配置できます。

planeのMaterial.colorWriteをfalseにしてみましょう。

<script>
  AFRAME.registerComponent('plane', {
    init: function () {
      const material = this.el.getObject3D('mesh').material;

      material.colorWrite = false;

      console.log(material);
    }
  });
</script>
<a-scene
  vr-mode-ui="enabled: false"
>
  <a-plane
    plane
    color="blue"
    width="99"
    height="1.2"
    position="0 -1 -5"
  ></a-plane>
  <a-box
    color="red"
    position="0 -1 -6"
    rotation="0 45 0"
    width="1.2"
    height="1.2"
    depth="1.2"
  ></a-box>
</a-scene>

すると、

f:id:kimizuka:20210106000810p:plain

という感じで、planの色は消えるものの、boxは隠れたままです。
一点注意事項としては、マスクとして使いたい要素(今回だとplane)を先にレンダリングする必要があること。

<a-scene
  vr-mode-ui="enabled: false"
>
  <a-box
    color="red"
    position="0 -1 -6"
    rotation="0 45 0"
    width="1.2"
    height="1.2"
    depth="1.2"
  ></a-box>
  <a-plane
    plane
    color="blue"
    width="99"
    height="1.2"
    position="0 -1 -5"
  ></a-plane>
</a-scene>

という感じで、レンダリングの順番を入れ替えるとマスクが効かなくなります。。
マスクとして使いたい要素を先にレンダリングしましょう。