Three.jsにLive2D組み込んでみたかったので、ちょっとトライしてみました。
WebGL(three.js)でレンズフレアと組み合わせたテストが上手くいった pic.twitter.com/wiE850pdcu
— naotaro (@naotaro0123) 2016年8月28日
開発環境
Live2D WebGL SDK2.1
Three.js(Revision:79)
実装内容
Live2D側へは、WebGLコンテキストが渡せば描画できるので以下のコードで渡しました。
// GLの取得の仕方
var renderer = new THREE.WebGLRenderer();
var gl = renderer.getContext();
// glをLive2Dに渡す
THREE.PlaneGeometryクラスのようなLive2Dクラスを作りたかったのですが、インデクスバッファやUV情報を渡すLive2D APIがないので以下のように実装しました。
1)Three.jsでオフスクリーンレンダリングを生成
2)オフスクリーンレンダリングでLive2D描画
3)オフスクリーンレンダリング結果をPlaneのテクスチャとして扱う
ソースコード
Three.jsと連携用にLive2DRender.jsというクラスを作りました。
(githubへもUPしておきました - Live2D_ThreeJS)
それ以外のクラスはLive2D WebGL SDKから持ってきてます。
Three.jsのbuildフォルダ配下に入れています。
HTML部分は、以下のように実装すればThree.js内でLive2D描画できます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Simple Live2D</title>
</meta>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="../../build/three.js"></script>
<!-- Live2Dのコアライブラリ -->
<script src="../../build/Live2D/lib/live2d.min.js"></script>
<!-- Live2Dの便利機能が入ったクラス群 -->
<script src="../../build/Live2D/framework/Live2DFramework.js"></script>
<!-- Live2Dモデルやテクスチャロード管理クラス -->
<script src="../../build/Live2D/src/PlatformManager.js"></script>
<!-- Live2Dモデルの生成やチェンジを行うクラス -->
<script src="../../build/Live2D/src/LAppLive2DManager.js"></script>
<!-- Three.js用のカスタムクラス -->
<script src="Live2DRender.js"></script>
<script>
// シーン生成
var scene = new THREE.Scene();
// カメラ生成
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
// レンダラー生成
var renderer = new THREE.WebGLRenderer();
// レンダラーのサイズ指定
renderer.setSize( window.innerWidth, window.innerHeight );
// DOMを追加
document.body.appendChild( renderer.domElement );
// オフスクリーン用(Live2Dを描画)
var offScene1 = new THREE.Scene();
var offRenderTarget1 = new THREE.WebGLRenderTarget(
window.innerWidth,
window.innerHeight,
{
minFilter: THREE.LinearFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat
}
);
var textureLoader = new THREE.TextureLoader();
// 背景テクスチャのロード
var background = textureLoader.load("../../assets/images/background.jpg");
// プレーン生成
var backgeo = new THREE.PlaneGeometry( 8, 8, 1, 1 );
var backmat = new THREE.MeshBasicMaterial( { map: background } );
var backmesh = new THREE.Mesh( backgeo, backmat );
scene.add( backmesh );
// Live2Dモデルパス
var MODEL_PATH1 = "../../assets/Epsilon2.1/";
var MODEL_JSON1 = "Epsilon2.1.model.json";
// Live2Dモデル生成
var live2dmodel1 = new THREE.Live2DRender( renderer, MODEL_PATH1, MODEL_JSON1 );
// オフスクリーンを描画するPlane生成
var geometry1 = new THREE.PlaneGeometry( 6, 6, 1, 1 );
// レンダーテクスチャをテクスチャにする
var material1 = new THREE.MeshBasicMaterial( { map:offRenderTarget1.texture } );
var plane1 = new THREE.Mesh( geometry1, material1 );
// この1行がないと透過部分が抜けない
plane1.material.transparent = true;
scene.add( plane1 );
// リサイズへの対応
window.addEventListener('resize', function(){
renderer.setSize( window.innerWidth, window.innerHeight );
// オフスクリーンのレンダーターゲットもリサイズ
offRenderTarget1.setSize( window.innerWidth, window.innerHeight );
// マウスドラッグ座標もリサイズ
live2dmodel1.setMouseView(renderer);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}, false);
// コンテキストメニューの表示を阻止
document.addEventListener('contextmenu', function(e){
// 右クリックの挙動を阻止する
e.preventDefault();
}, false);
// マウスクリック処理
document.addEventListener('mousedown', function(e){
switch(e.button){
case 0: // 左クリック
// ランダムモーション指定
live2dmodel1.setRandomMotion();
// 特定のモーション指定は、setMotion("ファイル名")を使う。
// 例:live2dmodel.setMotion("Epsilon2.1_m_08.mtn");
break;
case 2: // 右クリック
// ランダム表情切り替え
live2dmodel1.setRandomExpression();
// 特定の表情切り替えは、setExpression("ファイル名")を使う。
// 例:live2dmodel.setExpression("f04.exp.json");
break;
}
});
/**
* 描画処理
*/
var render = function () {
requestAnimationFrame( render );
// オフスクリーン切り替え描画
renderer.render( offScene1, camera, offRenderTarget1 );
// オフスクリーンにLive2D描画
live2dmodel1.draw();
// resetGLStateしないとgl.useProgramが呼ばれず以下のエラーになる
// [error]location is not from current program
renderer.resetGLState();
// Mainシーンで描画
renderer.render( scene, camera );
};
render();
</script>
</body>
</html>

応用編
これを応用するとThree.jsの機能も使えて色々できます!
・Live2Dを2体描画(DEMOページ)
・Cubeと組み合わせる(DEMOページ)
・レンズフレアと組み合わせる(DEMOページ)
古いjsで書いてすいませんが、こちらもgithubにソースUPしてあるので、興味ある人は参考にして下さい。