3Dモデルを読み込むためのオブジェクト jit.gl.model のテクスチャマッピングについて調査したので書き残しておきます。上記は様々な苦労の果てに描画された至極単純なシェーディングの一枚・・・涙
jit.gl.modelの裏側では assimp
jit.gl.modelでglTFのpbrマテリアルモデルを読み込むとテクスチャ・マテリアルが反映された状態のモデルが読み込まれます。
ここでJitter大好きおじさん達からしたら、「えっ、jit.gl.materialもjit.gl.pbrも、ましてやjit.gl.textureでテクスチャ指定してないのに何なん?」ってなりますよね。私はなりました。
これに対しては Max8 の最近のアップデートに
と書いてありました。理由もよくわかりませんが、適応されるんだなと暗記します。モデル付属のテクスチャも自動で読んでくれています。
ちなみにjit.gl.modelはさまざまなモデルファイルに対応していますが、裏側ではassimpというC / C++ ライブラリで出来ているようなのです。glTFなど最近の3Dモデルも問題なく読み込めるようになったりするのはこのライブラリが進化しているからだと予想できます。adobeがsupportしてgithubもそこそこ活発なようなので今後も開発は続けられると予想されますね。
jit.gl.modelのマテリアル
jit.gl.modelを描画する際に jit.gl.meshと組み合わせたり、マテリアルやシェーディングを色々といじりたくなりますがこれがハイパー難解でした。色々あったのですが結論だけ用途に合わせていくつかのパターンで紹介します。
パターン1 : デフォルト pbr マテリアルを利用
@material_mode というアトリビュートがあるので、こちらを3:JMTL(Use Jitter Material)としておけば、自動設定されたCycling74オススメのpbr materialになります。単に3Dを表示させるだけならこれでいいでしょう。
ただし、現状(8.5.4)だと roughness / metalness などの jit.gl.pbr でいじれるようなアトリビュートは変更できません。モデルのテクスチャによって設定されています。
つまり色合いを調整したかったら3Dソフトに戻って変更してねという事です。私は3Dソフトについては素人なので具体的な方法は分かりません。
デフォルトpbrの問題は jit.gl.enviroment などを利用して環境マップを設定しないとめちゃ暗いなどの問題もあります。またMaxで3Dをやる薄い理由の一つでもある @outputmatrix 1 をした瞬間に利用できなくなり、デフォルトpbrを利用したオーディオリアクティブなメッシュなどを作り出すことはできなさそうです。(やり方見つけた方いたら教えてください)
パターン2 : jit.gl.shader (GLSL)マテリアルを利用
では自分好みのシェーディングをしたい場合はどうでしょうか
@material_mode 0~3 に設定しておきます。そうすると一旦テクスチャが反映されていない状態になります。
続いて jit.gl.shader に@name xxx と名前をつけ、jit.gl.model @shader xxx と指定します。この時 @materialで指定しないように注意して下さい。
具体的にどのような色を描画するかGLSLのシェーダーを書きます。サンプルプログラムを下の方に載せてあります。ポイントは ” <param name=”modelTexture” type=”int” default=”0″/> ” の部分で、modelTextureという変数のインデックスを変更する事で albedo / normal / roughness / metallic / ambient occlusion / height / emission /emvironment などのUVマップ完了後テクスチャにアクセスできます。modelTextureというのは私がつけた名前なので好きな変数名に変更できますが、変数がsampler2DRectと結びつく事でこの挙動を引き出しているのでしょう・・・また番号と内容の対応は要調査が必要です。
例えば modelTexture0 ~ 5 などを default = “0” ~ “5” のように作成すると全てのテクスチャにアクセスしながらシェーディングが行えます。
jit.gl.shader の例
<jittershader name="simplematerial">
<description>
simple material for 3d model
</description>
<param name="modelViewProjectionMatrix" type="mat4" state="MODELVIEW_PROJECTION_MATRIX" />
<param name="textureMatrix0" type="mat4" state="TEXTURE0_MATRIX" />
<param name="position" type="vec3" state="POSITION" />
<param name="texcoord" type="vec2" state="TEXCOORD" />
<param name="modelTexture" type="int" default="0"/>
<language name="glsl" version="4.1">
<bind param="width" program="fp" />
<bind param="height" program="fp" />
<bind param="threshold" program="fp" />
<bind param="modelViewProjectionMatrix" program="vp" />
<bind param="textureMatrix0" program="vp" />
<bind param="position" program="vp" />
<bind param="texcoord" program="vp" />
<bind param="modelTexture" program="fp" />
<program name="vp" type="vertex">
<![CDATA[
#version 410
in vec3 position;
in vec2 texcoord;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 textureMatrix0;
out vec2 texcoord0;
void main( void )
{
gl_Position = modelViewProjectionMatrix*vec4(position, 1);
texcoord0 = vec2(textureMatrix0*vec4(texcoord, 0., 1.));
}
]]>
</program>
<program name="fp" type="fragment">
<![CDATA[
#version 410
in vec2 texcoord0;
// samplers
uniform sampler2D modelTexture;
out vec4 outColor;
// entry point
void
main()
{
outColor = texture(modelTexture,texcoord0).xyzw;
}
]]>
</program>
</language>
</jittershader>
パターン2 : 他のモデルのテクスチャをみてみよう
jit.gl.shader で様々なテクスチャを引いてこれる仕様を見つけるのが非常に困難で疲れた・・・のでもう少しお付き合いください。ひとつ車のモデルの例で見てみましょう。この画像自体はパターン1のデフォルトpbrシェーダーで描画されてます。やはり暗めですね。
この車のモデルには複数の元テクスチャがあるのですが、jit.gl.shaderで参照できるUVマップ後のテクスチャと比較してみましょう。
before(合成される前のテクスチャファイル)
after (jit.gl.model と jit.gl.shaderの組み合わせで取得できるテクスチャ)
なんと5種類しかないんですね。これは画像として用意されてる元のテクスチャをjit.gl.modelで読み込んだ瞬間に3D空間で使いやすい形式に再合成されているということですね。枚数が減ったからといって無駄になっているテクスチャはなさそうです。これを見つけるのに2日は費やしました。
パターン3(微妙):jit.gl.material や jit.gl.pbrを利用する
例えば、jitterのパターンとして jit.gl.model @outputomatrix 1 として内部のモデル行列をjit.gl.meshに送って描画する事があると思います。その時のテクスチャマッピングはjit.gl.meshに対してjit.gl.materialやjit.gl.pbr を接続し、jit.gl.textureなどを通して別途テクスチャを読み込み、マテリアルを反映させます。
ここで問題があります。パターン2の画像のように jit.gl.modelが1つのUVマップ後テクスチャを生成するのに複数の元テクスチャを利用していると、jit.gl.meshにおいて綺麗にテクスチャマッピんグをする事はできません。jit.gl.material / jit.gl.pbrに対して複数の元テクスチャを読み込みむ事ができないためですね。
この手法で上手く行く可能性があるのは元テクスチャとUVマップ後のテクスチャが1:1対応している場合なのかなと予想します。上記の車のテクスチャの例を見ると、8枚の画像から5枚のテクスチャを生成しており、albed以外でも複数の元テクスチャを参照してテクスチャマッピングをしているので様々3Dモデルを動的に読み込んで表現するのであればパターン3はオススメできません。
パターン2であれば、Vertex Shaderも使える!!!ので頂点・メッシュに対して変形処理を書くことができます。
まとめ
jit.gl.modelの難解なテクスチャマッピングの仕様を調査してみました。冒頭の画像はjit.gl.shaderでようやくシェーディングを描き始める事ができた画像という感じです。
昔JitterのVJを見る機会がありましたが jit.gl.gridshapeかjit.gl.platoなどのプリミティブな図形が利用されがちなのが理解できてきました。モデル読み込み&マテリアル適応の概念が難しすぎる。継承・関係性の仕様が隠蔽されていて厳しい!
今回の調査で自分でシェーダーを描きさえすれば好きなモデルを使えそうでという事で一歩前進したでしょうか。ぶっちゃけJitterは仕様を調べるのが大変すぎて何もつくれていません。MaxへのLoveで突き進んできましたが、これ以上理解が難しい問題があったら大人しくUnityかUnreal Engine使おうと思います。
リンク
3Dモデルはこちらからお借りしました ⇨ glTF Sample Model – https://github.com/KhronosGroup/glTF-Sample-Models