2021年11月5日
プログラミング
【Three.js×AR】マスクでポータルや擬似オクルージョンを実装する
はじめに
この記事ではThree.jsを使ったARのマスク表現の実装方法をご紹介します!
マスク(遮蔽)の表現を使うと、空間に穴が空いてるようなポータルっぽい表現ができたり、擬似的にオクルージョンっぽいことができたり…WebARでできる表現の幅が広がります。
基本的なマスクの実装
この記事ではマテリアルのオプションであるcolorWriteの設定を変えることでマスク表現をしていきます。
const material = new THREE.MeshBasicMaterial({ colorWrite: false });
colorWrite
は【マテリアルの色をレンダリングするかどうか】を指定できるプロパティです。
初期値は描画する(colorWrite: true
)ですが、falseにすることで
深度情報は持ったままレンダリングしない、つまり後ろにあるオブジェクトを隠す【見えないオブジェクト】を作成することができます。
マスクを使うときには、レンダリングする描画順を指定できる 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モデルを入れてみても楽しそうですね。
コードの全文はこちらから確認できます。
(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が顔の奥に回り込むのを自然に表現することができます。
まずは、顔部分を覆うための3Dモデルを用意します。
いい石仮面。
こちらの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());
};
完成したものはこちら!
フリー素材の人物写真で顔認識を行ってみましたが
顔の背後に位置する右耳のオブジェクトが顔の後ろに回り込んだように描画されていることがわかります。
マスクの大きさや位置を変えると回り込みの加減も調整できるのでお好みでいじってみてください。
まとめ
ポータルやオクルージョンを扱うと凝ったコンテンツに見えるものの、マスクを使うことでこんなに手軽に実装することができました!
もちろんかなり簡易的な方法ではありますが、WebARの表現手法のひとつとして試してみてはいかがでしょうか。
JavaScriptのお仕事に関するご相談
Bageleeの運営会社、palanではJavaScriptに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。
この記事は
参考になりましたか?
3
0
関連記事
2018年7月6日
【js】jQueryでできるハンバーガーメニューの作成
2018年6月18日
プログレスバーを簡単に実装できるprogressbar.js
2018年5月8日
画像に簡単にアニメーションをつけるcurtain.js
2018年2月14日
【js】jQueryでできるアコーディオンメニューの作成
2017年9月4日
【JS】スクロールした時にCSSanimationを発動させる「scrollMonitor」
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへpalanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー
Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。
やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。
はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。
ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。
Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。
ゲスト bagelee
かっきー
まりな
suzuki
miyagi
ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。
いわもと
デザイナーをしています。 好きな食べ物はラーメンです。
taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。
kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya
aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。
Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
sugimoto
asama
ando
iwasawa ayane
oshimo
異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!