各Cubism SDKの比較
最終更新: 2023年1月26日
Cubism SDK for Unity | Cubism SDK for Native | Cubism SDK for Web | Cubism SDK for Java |
|
マスクの共有 | CubismMaskControllerで指定したMaskTextureを共有 | モデル内だけで共有したマスクテクスチャを使用 | 同左 | 同左 |
マスクの枚数 | デフォルトで64枚のマスクが可能 | デフォルトで36枚のマスクが可能 ※高精細マスクを有効化することで制限を解除可能。 詳細は『マスクの前処理方式(Native)』を参照 |
デフォルトで36枚のマスクが可能 | デフォルトで36枚のマスクが可能 ※高精細マスクを有効化することで制限を解除可能。 詳細は『マスクの前処理方式(Java)』を参照 |
マスクの取り方 | マスクサイズは固定 マスクをかける側を内包できる正方形で構成する |
自動的なリサイズ マスクをかけられる側を内包できる矩形で マスク形状にいっぱいに構成する |
同左 | 同左 |
描画の方法 | 描画順(昇順降順)、Z値(昇順降順) | 描画順昇順のみ | 同左 | 同左 |
OWポーズ機能 | あり(R11 beta1~) | あり | 同左 | 同左 |
OW表情機能 | あり(R11 beta1~) | あり | 同左 | 同左 |
モーション管理 | Unityのmotion3.jsonをAnimationClipに変換し、 Mecanimで行う |
Cubism SDK for Nativeで行う | Cubism SDK for Webで行う | Cubism SDK for Javaで行う |
SDK使用言語 | C# | C++ | Type Script | Java |
Live2D配置 | GUI上 | コード上 | 同左 | 同左 |
出力先プラットフォーム | Windows, macOS, iOS, Android, WebGL, PlayStation 4, Nintendo Switch |
Windows, macOS, Linux, iOS, Android, PlayStation 4, Nintendo Switch |
Webブラウザ | Android |
マスク特性の違い
Cubism SDK for Unity
Unityではマスク画像の共有はCubismMaskControllerで指定されるMaskTexture単位で共有されます。
MaskTextureは複数作成することが可能で、同種のモデルであってもMaskTextureの指定が違えば別々に使用されます。
単一のモデルの中で複数のMaskTextureを使用することはできません。
テクスチャ一枚あたりのマスクの取り扱い枚数はMaskTextureのSubdivisionsの項目を変えることで変更することができます。
Subdivisionsの値は軸ごとのマスク取り扱い数で、以下の表のように取り扱い数が変化します。
Subdivisions | 1 | 2 | 3 | 4 | 5 |
マスク枚数 | 4 | 16 | 64 | 256 | 1024 |
標準ではマスクの取り扱い枚数に合わせてSubdivisionsを調整する機能はありません。
細かいマスクを必要とするモデルを扱うときには注意が必要です。
上の図はUnityで使用されるGloabalMaskTextureのRenderTextureをモデルと一緒に描画したものです。
右下の黒い部分がRenderTextureを描画したもので、左下から上へ下記の並びとなっています。
Mark1の目、Mark1の目、Mark1の口、名執の眼鏡、
名執の右目、名執の左目、Mark2の目、Mark2の目、
Mark2の口
同一のアートメッシュから生成されるマスクは統合されます。
これはマスクに使う番号を見ているわけではなく、インスタンス化したDrawableオブジェクトで比較しています。
そのため同一のモデルデータであっても複数インスタンスが存在した場合、インスタンスの数だけマスクを消費します。
マスクの上限に達した場合は実行時の登録順の遅いほうから、全面にマスクが掛かり表示が消えます。
また、マスクをかける側を内包する正方形で形状を取るため、大きなアートメッシュに小さなアートメッシュでマスクをかけても歪みにくい特性があります。
※AssetBundle化の際の注意
AssetBundle化した際にGloabalMaskTextureのRenderTextureが開放されない仕様があります。
メモリリークを起こさないためにチュートリアルの「AssetBundleからモデルを使用するとメモリリークする問題と対策」を確認してください。
Cubism SDK for Native、Cubism SDK for Web、Cubism SDK for Java
Cubism SDK for Native、Cubism SDK for Web, Cubism SDK for Javaでのマスクはモデル単位で冒頭で用意されます。
詳しくは「マスクの前処理方式」を確認してください。
Cubism SDK for Native、Cubism SDK for Web、およびCubism SDK for Javaではモデルごとにモデル内の描画順での描画機能しかないため、マスクの共有はモデル単位で行われます。
Unity同様同一マスクは統合されます。比較はDrawableの番号のみで行われます。
マスクの取り扱い枚数は最大36枚で、サイズは枚数によって自動的に調整されます。
上の図はCubism SDK for Nativeのクリッピングテクスチャを横に描画したものです。(Cubism SDK for Webでも同様の結果になります)
Cubism SDK for Native、Cubism SDK for Web、およびCubism SDK for JavaではCubism SDK for Unityと違って上下が逆転していることと、暗い方がマスクが描画されていることに注意してみてください。
描かれているのはMarkの右目、左目、口の3枚です。
Cubism SDK for Unityと違い、隣接するマスクバッファの影響を受けないためにマスクをかけられる側を内包する矩形で生成します。
このため、分割枚数が多い状態で大きなアートメッシュに小さなマスクが掛かるようなモデルでは、マスク領域がつぶれてしまい描画結果に影響が出る場合があります。
小さなマスクを離れた複数のアートメッシュに対してかける場合も同様です。
マスク領域がつぶれてしまう現象が発生した場合、マスクバッファのサイズを大きくすることで改善する場合があります。
(参考:マスクバッファの動的なサイズ変更)
また、Cubism SDK for Native、およびCubism SDK for Javaでは、パフォーマンスを引き換えにして高精細なマスクを使用する機能があります。
高精細マスクの有効化については『マスクの前処理方式(Native)#マスクの処理を高精細な方式に切り替える』、または『マスクの前処理方式(Java)#マスクの処理を高精細な方式に切り替える』をご覧ください。
描画順管理
Cubism SDK for Unity
Cubism SDK for Unityでは描画順の管理をUnity機能とスクリプトによって行っています。
方式は4つ。大分して2つの方法があります。
・Z調整(Back To Front Z、Front To Back Z)
モデル内のDrawableのZ位置をずらしてZソートによって描画順を修正する方法です。
カメラの設定がPerspectiveだったり、モデルのTramsformが回転していたりすると表示が乱れる可能性があります。
180度回転すると描画順は反転します。
描画順はすべてのDrawableに共通して同じ順序が振られます。
・Order調整(Back To Front Order、Front To Back Order)
モデル内のDrawableの描画順自体を一つづつずらして修正する方法です。
カメラの設定やモデルの回転で表示は乱れません。裏面であっても描画順はカメラに向かって同一です。
CubismRenderControllerのOrder In Layerを各モデルで十分に空けない場合、
描画順が混在し、細かく切り替わる状態になります。
DrawCallが増大したり、表示位置が被った状態だとDrawableが混じった表示になることがあります。
逆にUnityのオブジェクトなどをモデルの描画に挟み込むことにより、オブジェクトを持ったように見せかけたりすることもできます。
Cubism SDK for Native、Cubism SDK for Web、Cubism SDK for Java
Cubism SDK for Native、Cubism SDK for WebおよびCubism SDK for Javaではモデルに紐づけられたRendererの中身で描画順をソートします。
// Cubism SDK for Native void CubismRenderer_OpenGLES2::DoDrawModel() { ・ ・ ・ const csmInt32 drawableCount = GetModel()->GetDrawableCount(); const csmInt32* renderOrder = GetModel()->GetDrawableRenderOrders(); // インデックスを描画順でソート for (csmInt32 i = 0; i < drawableCount; ++i) { const csmInt32 order = renderOrder[i]; _sortedDrawableIndexList[order] = i; } // 描画 for (csmInt32 i = 0; i < drawableCount; ++i) { const csmInt32 drawableIndex = _sortedDrawableIndexList[i]; ・ ・(中略) ・ DrawMesh( GetModel()->GetDrawableTextureIndices(drawableIndex), GetModel()->GetDrawableVertexIndexCount(drawableIndex), GetModel()->GetDrawableVertexCount(drawableIndex), const_cast<csmUint16*>(GetModel()->GetDrawableVertexIndices(drawableIndex)), const_cast<csmFloat32*>(GetModel()->GetDrawableVertices(drawableIndex)), reinterpret_cast<csmFloat32*>(const_cast<Core::csmVector2*>(GetModel()->GetDrawableVertexUvs(drawableIndex))), GetModel()->GetDrawableOpacity(drawableIndex), GetModel()->GetDrawableBlendMode(drawableIndex) ); } }
// Cubism SDK for Web public doDrawModel(): void { ・ ・ ・ const drawableCount: number = this.getModel().getDrawableCount(); const renderOrder: Int32Array = this.getModel().getDrawableRenderOrders(); // インデックスを描画順でソート for (let i = 0; i < drawableCount; ++i) { const order: number = renderOrder[i]; this._sortedDrawableIndexList.set(order, i); } // 描画 for (let i = 0; i < drawableCount; ++i) { const drawableIndex: number = this._sortedDrawableIndexList.at(i); ・ ・(中略) ・ this.drawMesh( this.getModel().getDrawableTextureIndices(drawableIndex), this.getModel().getDrawableVertexIndexCount(drawableIndex), this.getModel().getDrawableVertexCount(drawableIndex), this.getModel().getDrawableVertexIndices(drawableIndex), this.getModel().getDrawableVertices(drawableIndex), this.getModel().getDrawableVertexUvs(drawableIndex), this.getModel().getDrawableOpacity(drawableIndex), this.getModel().getDrawableBlendMode(drawableIndex), this.getModel().getDrawableInvertedMaskBit(drawableIndex) ); } }
// SDK for Java @Override protected void doDrawModel() { ... final int drawableCount = model.getDrawableCount(); final int[] renderOrder = model.getDrawableRenderOrders(); // Sort the index by drawing order for (int i = 0; i < drawableCount; i++) { final int order = renderOrder[i]; sortedDrawableIndexList[order] = i; } ... // Draw process for (int i = 0; i < drawableCount; i++) { final int drawableIndex = sortedDrawableIndexList[i]; ... drawMeshAndroid( model.getDrawableTextureIndex(drawableIndex), model.getDrawableVertexIndexCount(drawableIndex), model.getDrawableVertexCount(drawableIndex), indexArrayBuffer, vertexArrayBuffer, uvArrayBuffer, model.getMultiplyColor(drawableIndex), model.getScreenColor(drawableIndex), model.getDrawableOpacity(drawableIndex), model.getDrawableBlendMode(drawableIndex), model.getDrawableInvertedMask(drawableIndex) // Whether the mask is used inverted ); } postDraw(); }
モデル間で表示が混じることはありません。
モデル間では先に描画したほうが後ろに表示されます。
モーションの管理
Cubism SDK for Unityではモーションの管理をUnity機能であるMecanimと、UnityのPlayable APIを利用したSDK付属のコンポーネント「CubismMotionController」の2種類を使用して行います。
Mecanimではグラフィカルな環境で視覚的にモーションの組み合わせを設計できます。
CubismMotionControllerでは状態を気にせずすべてスクリプトからモーションを再生することが出来ます。
Cubism SDK for Native、Cubism SDK for WebおよびCubism SDK for JavaではLive2D側のSDKでモーション管理を行います。
直接コードで操作する形になりますが、ポーズ機能などCubism 2.1に近い形での運用ができます。
詳しいSDKによるモーション関連の違いについては「SDKによるモーション作成の違いについて」を参照してください。