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

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

Three.jsに読み込んだglbファイルのマテリアルを透明にする 👀

マテリアルの変更は以前調べた し、なんならその時も半透明にしたから大丈夫でしょう。

blog.kimizuka.org

と思って、取り組んだのですが、ハマったのでメモを残しておきます。

まず、glbファイルを読み込みます。

f:id:kimizuka:20210715133637p:plain

前回の記事を参考にmaterialを透明にします。
(半透明ではなく透明にしました)

object.material.transparent = true;
object.material.opacity = 0;


すると、

f:id:kimizuka:20210715133854p:plain

透明になりましたが、なんか想像と違う!
裏に置いてある壁が見えなくなってしまっています。一昔前のジャニーズ感がありますね。

モデルを透明にしつつ、背景も見せたい。
いろいろ試してみた結果、alphaToCoverageたるプロパティをtrueに設定すればいけることがわかりました。

threejs.org

object.material.transparent = true;
object.material.alphaToCoverage = true; // 追加
object.material.opacity = 0;

これで結果を見てみると、

f:id:kimizuka:20210715134314p:plain

透明になりました!

が。透明にしちゃうと、ちゃんと表示されているのかわからないです。
なので、半透明を比較してみましょう。

まずは、alphaToCoverageをfalseにした結果。

object.material.transparent = true;
object.material.alphaToCoverage = false;
object.material.opacity = .6;

f:id:kimizuka:20210715134419p:plain

やや白いです。裏に置いてある壁は見えません。
半透明といったので、opacityを0.5に設定すればよかったと思いつつ、もうスクショ撮っちゃったので、0.6のまま突き進みます。

つぎに、alphaToCoverageをtrueにした結果。

object.material.transparent = true;
object.material.alphaToCoverage = ture;
object.material.opacity = .6;

f:id:kimizuka:20210715134517p:plain

半透明です。裏に置いてある壁も見えてます。これが望んでいた結果です。

なので、alphaToCoverageをtrueにすればオールオーケーです。

一応、半透明バージョンのソースを全部載せておきます。
同一階層にmodel.glbを置けば動くと思います。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>alphaToCoverage</title>
  <style>
    * {
      margin: 0; padding: 0;
    }

    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r127/three.min.js"></script>
  <script src="https://cdn.rawgit.com/mrdoob/three.js/r127/examples/js/loaders/GLTFLoader.js"></script>
  <script>
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
      60,
      window.innerWidth / window.innerHeight,
      1,
      100
    );

    camera.position.set(0, 1, 3);
    scene.add(camera);

    const renderer = new THREE.WebGLRenderer({
      antialias : true,
      alpha: true
    });

    renderer.outputEncoding = THREE.GammaEncoding;
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);

    document.body.appendChild(renderer.domElement);

    const loader = new THREE.GLTFLoader();
    const url = './model.glb';

    loader.load(
      url,
      (gltf) => {
        const model = gltf.scene;

        model.traverse((object) => {
          if (object.isMesh) {
            object.material.trasparent = true;
            object.material.alphaToCoverage = true;
            object.material.opacity = .6;
          }
        });

        model.scale.set(1, 1, 1);
        model.position.set(0, 0, 0);

        scene.add(model);

        renderer.setAnimationLoop(tick);
      },
      (err) => {
        console.error(err);
      }
    );

    const light = new THREE.AmbientLight(0xFFFFFF, 1.0);

    scene.add(light);

    const geometry = new THREE.PlaneGeometry(16, 16, 1, 1);
    const material = new THREE.MeshStandardMaterial({
      color: 0xFF0000
    });
    const wall = ground = new THREE.Mesh(geometry, material);

    wall.position.set(0, 0, -4);
    wall.rotation.set(0, 0, 0);

    scene.add(wall);

    function tick() {
      renderer.render(scene, camera);
    }
  </script>
</body>
</html>