- 1 はじめに
- 2 経緯
- 3 作成したデモについて
- 4 PlayCanvasと生成系AIを組み合わせたデモの実装について
- 5 3Dモデルをゲームエンジン(PlayCanvas)で利用する方法
- 6 あとがき。
はじめに
GMOグローバルサイン・ホールディングスの羽賀(@mxcn3)です。ゲームエンジンPlayCanvasの日本コミュニティ運営や、テクニカルサポートを担当しております。GPUインスタンスと生成系AIを組み合わせて作成したデモプロジェクトの検証結果を紹介いたします。
経緯
この記事を書くきっかけとなったのは、全社的な生成系AIの取り組み強化を目指し、2023年6月21日に始まった「AI 活用 No.1 企業グループへの取組を加速全パートナー向け、NVIDIA 社最新 GPU 搭載サーバー/ノートパソコンの無償貸出を実施」プログラムにより、GPUインスタンスを借りたことです。
ノートパソコンの貸与やサーバーの貸与が受けられますが、サーバー利用の際に貸与されるGPUインスタンスは、「NVIDIA H100 (VRAM 80GB)」または「NVIDIA L4 (VRAM 24GB)」です。本記事での検証内容は、NVIDIA L4を利用したものです。
作成したデモについて
WebGLベースのゲームエンジン、PlayCanvasと生成系 AI を組み合わせて3Dシーンを生成するデモを作成しました。
テキストを入力すると、仮の3Dシーンが配置されます。配置された3Dシーンのオブジェクトをクリックすると、その3Dモデルが生成されます。ボクセル化といった機能も提供しており、生成されたモデルデータは .glb形式のモデルデータ でダウンロード可能です。
ウェブブラウザからアクセスできるようになっていますので、ぜひお試しください。
https://playcanv.as/e/p/xl9NWKYg/
※ デモは2023年 7月31日まで公開予定です。
PlayCanvasと生成系AIを組み合わせたデモの実装について
以下がこのデモで実行している内容です。この内容に沿ってそれぞれの実装と検証について説明します。
- プロンプトから3Dシーンの生成
- プロンプトから3Dモデルの生成
- GPUインスタンス上で Blender を用いた UV 展開とモディファイアの適用
- 生成した 3D モデルデータのダウンロード
1. プロンプトから3Dシーンの生成
デモにアクセスすると、最初に、3D モデルの生成画面が表示されます。この画面ではプロンプトで入力した内容を元に、3Dシーンを作成ができます。
構成について
この部分では、3Dの描画にPlayCanvas、シーンデータの作成にChatGPTのAPIを利用してシーン作成しました。実際にどのようにChatGPTを用いて3Dシーンが作成されるのかを解説します。
PlayCanvas
PlayCanvasは、ウェブ上で3Dコンテンツを作成するためのプラットフォームです。ゲームエンジンのみを使用する場合は、Three.jsやBabylon.jsなどのWebGLライブラリと同様の方法で利用できます。PlayCanvasエディターを使用すると、共同編集機能やコードエディターなどを使用できます。プロジェクトの作成から公開まで、すべてをクラウド上で行うことができる便利なツールです。
ChatGPT API
ChatGPT APIは、OpenAIが提供するAPIの一部で、ChatGPTをプログラムから利用するためのものです。ChatGPT APIを使用することで、開発者は自身のアプリケーションやサービスにChatGPTの機能を組み込むことができます。
ChatGPT API Function calling
2023年 6月13日のFunction calling and other API updatesのアップデートにより、ChatGPTのAPIにFunction callingの機能が追加されました。これにより、ChatGPT APIの出力をテキストではなく、JSONオブジェクト形式で受け取ることができます。
Function callingを使用して3Dシーンの出力をする
Function callingの設定と呼び出しは以下のように行います。ChatGPTのAPIモデルとしてgpt-3.5-turbo-16kを利用します。例えば、今回のデモの実装では、Node.jsを利用してPlayCanvasから「公園」という入力がされた場合には、以下のように呼び出します。
const configuration = new Configuration({ apiKey: `your-api-key` });
const openai = new OpenAIApi(configuration);
const systemMessage = { role: "system", content: `3Dモデルのシーンを作成してください` }; // システムメッセージ
const userMessage = { role: "user", content: `公園` }; // ユーザーから入力されたプロンプト
const createCompletionRequest = {
model: "gpt-3.5-turbo-16k",
messages: [systemMessage, userMessage],
function_call: "auto",
functions: [
{
name: "generateSceneObjects",
description: "3Dのシーンのオブジェクト一覧を作成",
parameters: {
type: "object",
properties: {
SceneObjects: {
type: "array",
items: {
name: {
// 3Dオブジェクトの名前
type: "string",
},
position: {
// 3Dオブジェクトの座標
type: "array",
items: {
type: "number",
},
},
rotation: {
// 3Dオブジェクトの回転
type: "array",
items: {
type: "number",
},
},
scale: {
// 3Dオブジェクトのスケール
type: "array",
items: {
type: "number",
},
},
},
},
},
required: ["SceneObjects"],
},
},
],
};
const completion = await openai.createChatCompletion(createCompletionRequest);
期待するレスポンスをfunctions内に定義し、ChatGPT のcreateChatCompletion
を呼び出します。Function calling がChatGPTのAPI側で生成ができる場合には、required
に指定されたSceneObjects
含むレスポンスが返ってきます。
const completion = await openai.createChatCompletion(createCompletionRequest);
const message = completion.data.choices[0].message;
// Function calling が利用されたかの判定
if (message.function_call) {
const response = JSON.parse(message?.function_call.arguments);
const sceneObjects = response.SceneObjects;
// 結果を出力
console.log(sceneObjects);
// [
// {
// name: "オブジェクト名",
// position: [0, 0, 0],
// rotation: [0, 0, 0],
// scale: [1, 1, 1]
// }
// ]
}
Function callingが使用されなかった場合にも message.function_call の値を元に判定ができます。今回のデモも同様に、Function callingが呼び出された場合にPlayCanvas側にレスポンスを返しています。
Function callingを利用せずに行う場合、受け取ったテキストデータをパースする必要がありますが、出力が安定しないことがあります。しかし、この機能を利用することで開発者が望むデータをある程度作成できます。
以上の手順により、複数のオブジェクトを含んだ3Dシーンを構築することができました。
2. プロンプトから3Dモデルの生成
先程生成された3Dシーンのモデルから、3Dモデルの生成を行います。3Dシーン上では自由にカメラの移動ができるため、好きなオブジェクトをクリックすることで3Dモデルを生成できます。
構成について
以下のような構成でウェブAPIとしてリクエストを受け取り、GPUインスタンス上で3Dモデルを生成して、PlayCanvasに対して“.glb形式の3Dモデルのデータ`を返却しています。
サーバーのスペック
今回、サーバーのスペックは以下のとおりです。L4のGPUインスタンスを活用し、サーバー上で3Dモデルを生成しています。
- Ubuntu 22.04.2 LTS
- メモリ 128GB
- VRAM 24GB (NVIDIA L4)
- ディスク 1TB
Shap-Eについて
Shap-Eは、OpenAIが公開しているテキストや画像から3Dモデルを生成するためのツールです。このツールはMITライセンスで公開されており、公式のGitHubには利用方法が掲載されており、ローカル環境でも実行可能です。
GPUインスタンスでのShap-E の実行
FastAPI を使ってShap-Eを利用して3Dモデルの生成と返却を行っています。
HuggingFaceにて公開されている、「hysts/Shap-E」を参考に作成いたしました。
Shap-Eには、プロンプト(prompt)、シード(seed)、ガイダンススケール(guidance_scale)、ステップ数(num_steps)の入力があります。これらの情報を受け取り、モデルデータの生成を行い、.glb形式のモデルデータを返却しています。
以上がShap-Eの概要とGPUインスタンスでの実行に関する説明です。
from fastapi import FastAPI, UploadFile, File, HTTPException, Query
from fastapi.responses import JSONResponse
from pathlib import Path
from starlette.responses import FileResponse
from model import Model # Shap-Eのインポート
app = FastAPI()
model = Model()
@app.get("/model/generate/")
async def generate_model(
prompt: str = Query("A chair that looks like an avocado"),
seed: int = Query(0),
guidance_scale: float = Query(15),
num_steps: int = Query(64)
):
try:
glb_path = model.run_text(prompt, seed, guidance_scale, num_steps)
path = Path(glb_path)
if path.is_file():
return FileResponse(path, media_type='model/gltf-binary', filename="model.glb")
except Exception as e:
raise HTTPException(status_code=500, detail=e)
データ形式の説明
今回生成されることになるモデルデータは、.glb
形式です。.glb
形式とは、ウェブ上で3Dコンテンツを効率的に表示するための規格であり、WebGL系のライブラリ、PlayCanvas等で広くサポートされています。
.glb形式モデルデータのブラウザ上での描画
PlayCanvasでは、.glb
形式のモデルデータをブラウザ上で描画するためにloadFromUrlAndFilename
メソッドが使用されます。コードは以下の通りです。
const url = `/model/generate/?prompt=プロンプト`;
pc.app.assets.loadFromUrlAndFilename(url, `model.glb`, "container", (err, asset) => {
const object = asset.resource.instantiateRenderEntity(); // APIレスポンスから3Dモデルデータを読み込みます
this.entity.addChild(object); // シーンに3Dモデルを追加します
// ... すでに存在するモデルデータの削除処理
});
この実装により、Shape-Eを利用して、GPUインスタンス上で生成された3DモデルをPlayCanvas上で表示することが可能となりました。
3.GPUインスタンス上でBlenderを用いたUV展開とモディファイアの適用
モデルデータのダウンロード機能の実装が完了したので、次に、GPUインスタンス上でBlenderを用いることを試みました。Shap-Eにより生成されたモデルは、色の決定に頂点カラーを使用しています。また、モデルデータの整形も含めて、Blenderを用いてUV展開とモディファイアの適用を行いました。
構成について
こちらの実装ではShap-Eで生成されたモデルに対して3Dモデルの編集の処理として、Blenderを利用してUV展開とモディファイアの適用を行っています。
Blender
Blender(ブレンダー)は、オープンソースの3Dコンピュータグラフィックスソフトウェアです。3Dモデリング、アニメーション、レンダリング、ビデオ編集など、多岐にわたる機能を提供しています。
GPUインスタンスでBlenderの実行
今回の検証をして初めて知ったのですが、GPU インスタンス上で Blender を実行することができます。Blender は実行ファイルに--background
の引数を渡すことでヘッドレスモードで起動ができます。
blender --background
バックグラウンドで起動した場合でも、 .blend
ファイルというBlenderのプロジェクトファイルを与えて起動することができます。 .blend
ファイルを渡すには -b
オプションをつけます。
blender --background -b xxxxxx.blend
以下のコードで、GPUインスタンスで生成されたモデルに対してリメッシュとスマートUV展開が行っています。
import bpy
import sys
# Blender の引数を取得
argv = sys.argv
argv = argv[argv.index("--") + 1:] # '--' 以降がスクリプトの引数
input_path, output_path = argv[0], argv[1]
# 入力となる 3D モデルを読み込みます。
bpy.ops.import_scene.gltf(filepath=input_path)
# インポートされた全てのメッシュに対し、リメッシュとスマートUV展開を適用します。
for obj in bpy.context.scene.objects:
if obj.type == 'MESH':
# アクティブなオブジェクトを設定します。
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
# Remesh モディファイアを追加します。
modifier = obj.modifiers.new(name="Remesh", type='REMESH')
modifier.mode = 'BLOCKS'
modifier.octree_depth = 5 # Remesh の解像度を設定します。値が大きいほど詳細になりますが、その分、計算時間も増えます。
# モディファイアを適用します。
bpy.context.view_layer.objects.active = obj
bpy.ops.object.modifier_apply(modifier="Remesh")
# UV 展開のために Edit モードに切り替え、全ての頂点を選択します。
bpy.ops.object.mode_set(mode='EDIT') # Edit モードに切り替えます。
bpy.ops.mesh.select_all(action='SELECT') # 全ての頂点を選択します。
bpy.ops.uv.smart_project() # スマートUV展開を実行します。
bpy.ops.object.mode_set(mode='OBJECT')
# 結果を保存します。
bpy.ops.export_scene.gltf(filepath=output_path)
この実装により、UVマップが生成され、生成された3Dモデルにテクスチャを適用可能です。
4. Shap-E で生成されるモデルデータのクオリティについて
Shape-E では、プロンプトの他にモデルのクオリティを指定するパラメータを設定できます。このパラメーターは、生成されるモデルの質を調整するもので、数値が大きいほどモデルのクオリティが向上します。デフォルトのステップ数は64
で、その値を変更してそれぞれのシーンを生成した際の、生成時間と生成モデルデータのクオリティを検証しました。
※ 生成時間は3Dモデル毎の生成にかかる時間の目安となります。
各パラメーターによる生成時間とクオリティの変化
1.
2.
3.
4.
5.
6.
7.
生成時間と生成されるモデルデータの品質を考慮して、今回のデモプロジェクトではステップ数を64
に固定して生成を行いました。
5.生成した 3D モデルデータのダウンロード
デモプロジェクトでは、右上のダウンロードボタンを押すと、シーンのデータを.glb形式
の3Dモデルデータとしてダウンロードできます。
生成された3Dモデルは.glb形式
のモデルデータであるため、Blenderなどの3Dモデリングソフトで編集可能です。
シーンのエクスポートについては、PlayCanvasを用いて実装しています。
詳細はこちらの記事「PlayCanvas エディターのシーンを動的に GLB / USDZ としてエクスポートをする」をご覧ください。
3Dモデルをゲームエンジン(PlayCanvas)で利用する方法
今回は最後に、作成したモデルデータを利用して、3Dウォークスルーシーンを作成してみましょう。
生成された.glb形式
のモデルデータはPlayCanvas等のゲームエンジンで読み込むことができます。
PlayCanvasにモデルデータをインポートすることにより、以下のようなシーンが作成できます。
PlayCanvasはキャラクターコントロールのためのFirst Person Controllerアセットをアセットストアから利用可能です。このアセットをシーンに追加することで、WASDキーによる移動が可能なプロジェクトを作成できます。
次に、地面に対してコライダーを設定します。PlayCanvasではエディタ上から直接、コライダーの設定ができます。
以上の手順により、GPUインスタンスを使用して作成した3Dモデルをゲームエンジン(PlayCanvas)上で操作できるようになりました。
こちらもURLからアクセスができますのでぜひお試しください。
デモ URL: https://playcanv.as/e/p/s5YwrvK0/
あとがき。
今回は、GPUインスタンスを活用し、生成系AIを用いた3Dシーンの生成について検証しました。GPUインスタンスの使用により、3Dモデルを生成した後にBlenderなどの3Dモデリングソフトを動かし、UV展開やモディファイアの適用などを行うことが可能であることを確認しました。
まだ改善の余地はいくつか存在しますが、モックデータの作成などについて今後利用可能になる可能性があると思われます。
質問や不明点がありましたら、Twitterの@mxcn3までお問い合わせください。