2021年11月5日

プログラミング

【Three.js×AR】マスクでポータルや擬似オクルージョンを実装する

目次

  1. はじめに
  2. 基本的なマスクの実装
  3. 応用① ポータル表現
  4. 応用② 擬似オクルージョン表現
  5. まとめ

はじめに

この記事ではThree.jsを使ったARのマスク表現の実装方法をご紹介します!

マスク(遮蔽)の表現を使うと、空間に穴が空いてるようなポータルっぽい表現ができたり、擬似的にオクルージョンっぽいことができたり…WebARでできる表現の幅が広がります。

基本的なマスクの実装

この記事ではマテリアルのオプションであるcolorWriteの設定を変えることでマスク表現をしていきます。

const material = new THREE.MeshBasicMaterial({ colorWrite: false });

colorWrite は【マテリアルの色をレンダリングするかどうか】を指定できるプロパティです。
初期値は描画する(colorWrite: true)ですが、falseにすることで
深度情報は持ったままレンダリングしない、つまり後ろにあるオブジェクトを隠す【見えないオブジェクト】を作成することができます。

スクリーンショット 2021-11-05 8.56.31.png (1.5 MB)

マスクを使うときには、レンダリングする描画順を指定できる renderOrderを使い、マスク用のオブジェクトの描画順を一番早く指定することで想定通りの描画をすることができます。

このcolorWrite: falseを表現に応用してみましょう!

応用① ポータル表現

ポータルとはARに使われる表現方法の一つで
現実世界のなかに仮想空間への入り口が開いているような表現に対して使われる言葉です。

今回は【マーカーの奥に空間があるように見えるポータル表現】を、マスクを使って実装してみたいと思います。

実装の手順

  • 1. boxを二つ重ねる
  • 2. 外側のboxをマスク用のboxとして、表面部分(覗き込みたい部分)の面を削除する
  • 3. 内側のboxは覗き込んだ中の空間を表示するものとして、materialのsideをBackSideにする
  • 4. 外側のboxのマテリアルにcolorWrite: falseを適用する
  • 5. 外側のboxを内側のboxより少しだけ大きくして重ねる

実際に書いてみるとこんな感じです。


  // 1. boxを二つ重ねる
  const insideGeo = new THREE.CubeGeometry(1, 1, 1);
  const outsideGeo = new THREE.CubeGeometry(1, 1, 1);

  // 2. 外側のboxをマスク用のboxとして、表面部分(覗き込みたい部分)の面を削除する
  outsideGeo.faces.splice(4, 2);

  // 3. 内側のboxは覗き込んだ中の空間を表示するものとして、materialのsideをBackSideにする
  const insideMat = new THREE.MeshLambertMaterial({
    side: THREE.BackSide,
  });

  // 4. 外側のboxのマテリアルにcolorWrite: falseを適用する
  const invisibleMat = new THREE.MeshBasicMaterial({ colorWrite: false });
  const insideBox = new THREE.Mesh(insideGeo, insideMat);
  const outsideBox = new THREE.Mesh(outsideGeo, invisibleMat);
  outsideBox.renderOrder = -1;

  // 5. 外側のboxを内側のboxより少しだけ大きくして重ねる
  outsideBox.scale.multiplyScalar(1.05);
  outsideBox.position.set(objectParam.x, objectParam.y, objectParam.z);
  insideBox.position.set(objectParam.x, objectParam.y, objectParam.z);
  scene.add(insideBox);
  scene.add(outsideBox);

完成形はこちら。
マーカーの奥に穴が開いているような、不思議な表現ができました。

奥行きをもっと深くしてみたり、内側の壁にテクスチャを貼ってみたり、また箱の中に3Dモデルを入れてみても楽しそうですね。

giphy.gif (6.2 MB)

giphy.gif (2.9 MB)

コードの全文はこちらから確認できます。
(AR.jsのHiroマーカーをかざすことで実際に挙動の確認もできます。)

See the Pen
Three.js x AR.js mask test
by Damien (@Damien_Ito)
on CodePen.

参考
AR.js example
Three.js and AR.js Examples

応用② 擬似オクルージョン表現

今度はこのマスクを応用して、オクルージョンを疑似的に実現してみようと思います。

オクルージョンといえば、奥に配置した3DCGが手前の現実物体に遮蔽されてるかのように欠けた状態で描画する表現のこと。
しかし遮蔽用のマスクを用意しておいても、この方法だと限定的なシーンでしかオクルージョンを表現できないため、活用方法が難しいと感じるかもしれません。

そんな擬似オクルージョンが最大の威力を発揮するのは顔認識AR

顔認識ARにて、顔周辺にメガネやピアスなどの3DCGをつけたいとき
顔を横に向けると3DCGが顔の上に描画されてしまい綺麗な見た目にはなりません。

そこで、人の顔にあたる部分に今回の遮蔽マスクを使ってみましょう。
こうすることで、3DCGが顔の奥に回り込むのを自然に表現することができます。
img.png (196.2 kB)

まずは、顔部分を覆うための3Dモデルを用意します。

スクリーンショット 2021-10-06 15.33.07.png (652.7 kB)

いい石仮面。
こちらの3Dモデルは社内で用意していますが、3Dモデル販売サイトにはこんな感じの3Dモデルが結構あると思いますのでぜひ探してみてください。

とりあえず試しに動かしてみたい!という方は、一旦プリミティブのcubeオブジェクトで代用してもいいと思います。

また、今回は顔認識ライブラリとしてjeelizFaceFilterを使います。
(jeelizFaceFilterの詳しい使い方は割愛します)

実装の手順

  • 1. メガネやピアスなどのパーツを顔周りに配置
  • 2. マスク用の仮面3Dモデルを顔に合うように配置する
  • 3. 仮面3DモデルにcolorWrite: falseを当てる

早速実装してみましょう!


// 1. メガネやピアスなどのパーツを顔周りに配置
// ピアス用のジオメトリ、マテリアルを作成
const earringGeometry = new THREE.IcosahedronGeometry(1);
const earringMaterial = new THREE.MeshNormalMaterial();

// ピアスオブジェクトの作成
const earring1 = new THREE.Mesh(earringGeometry, earringMaterial);
earring1.position.set(0.74, -0.04, -0.5);
earring1.scale.set(0.17, 0.17, 0.17);
threeStuffs.faceObject.add(earring1.clone());

const earring2 = new THREE.Mesh(earringGeometry, earringMaterial);
// 左右同じpositionにした場合少しズレて見えたので変更しています。この辺りはお好みで
earring2.position.set(-0.7, -0.03, -0.5);
earring2.scale.set(0.17, 0.17, 0.17);
threeStuffs.faceObject.add(earring2.clone());

const invisibleMaterial = new THREE.MeshBasicMaterial({ colorWrite: false });
const loader = new GLTFLoader();

// 顔部分のマスクオブジェクトを作成
loader.load("./src/3d/face.gltf", (model) => {
  const root = model.scene;
  // 2. マスク用の仮面3Dモデルを顔に合うように配置する
  root.scale.set(0.5, 0.5, 0.5);
  root.position.set(0, 0, 0.35);
  // 3. 仮面3DモデルにcolorWrite: falseを当てる
  root.material = invisibleMaterial;
  root.renderOrder = -1;
  threeStuffs.faceObject.add(root.clone());
};

完成したものはこちら!

giphy (2).gif (4.2 MB)

フリー素材の人物写真で顔認識を行ってみましたが
顔の背後に位置する右耳のオブジェクトが顔の後ろに回り込んだように描画されていることがわかります。

マスクの大きさや位置を変えると回り込みの加減も調整できるのでお好みでいじってみてください。

まとめ

ポータルやオクルージョンを扱うと凝ったコンテンツに見えるものの、マスクを使うことでこんなに手軽に実装することができました!

もちろんかなり簡易的な方法ではありますが、WebARの表現手法のひとつとして試してみてはいかがでしょうか。

JavaScriptのお仕事に関するご相談

Bageleeの運営会社、palanではJavaScriptに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。

無料相談フォームへ

2

0

AUTHOR

damien

Damien

WebAR/VRを中心に企画・マークアップ・開発をやっています。森に住んでいます。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

簡単に自分で作れるWebAR

「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。

palanARへ
palanar

palanはWebARの開発を
行っています

弊社では企画からサービスの公開終了まで一緒に関わらせていただきます。 企画からシステム開発、3DCG、デザインまで一貫して承ります。

webar_waterpark

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

kobori

こぼり ともろう エンジニア

サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

sasai

ささい エンジニア

フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

damien

Damien

WebAR/VRを中心に企画・マークアップ・開発をやっています。森に住んでいます。

ゲスト bagelee

ゲスト bagelee

かっきー

かっきー

まりな

まりな

suzuki

suzuki

taro

taro

xR界隈のビズをやっています。新しいガジェットとか使うのが好きです。あとお寿司は玉子のお寿司が好きです。

miyagi

ogawa

ogawa

雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。

いわもと

いわもと

kobari

taishi kobari

フロントエンドの開発を主に担当してます。Blitz.js好きです。

shogokubota

kubota shogo

サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!

nishi tomoya

aihara

aihara

グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。

nagao

SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。

kainuma

Kainuma

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

sugimoto

sugimoto

CONTACT PAGE TOP