プロフィール

Na-7

Author:Na-7
SE(システムエンジニア)として約15年間システム系ソフト会社を勤めあげ、2008年3月退社。現在、ゲーム制作会社設立を目指して活動中。


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
DATE: CATEGORY:三国志軍記開発
NormalMappingEffectサンプル
NormalMappingEffectサンプル
法線マップを読み込むサンプル。実行すると、モデルの周囲をライトが回転し、凹凸が強調される。



◎調査開始

複数のテクスチャを貼り付けるにはどうすれば良いか?
技術調査を開始して、最初に見付けたのはこの記事です。

この質問は私の疑問に近い気がしますが、自己レスの結論の部分で具体的に何をしたのかがわかりません。
カスタムエフェクトを作成したのか?エフェクトパスを複数用意したのか?

この謎を解くためには「そもそもEffectクラスの中でテクスチャはどのように管理されているのか?」から確認する必要がありそうです。その上で、複数テクスチャの登録手順や表示手順を調べていくべきでしょう。



◎サンプル解析

一方、先のQ&Aの中で、NormalMappingEffectSampleというサンプルが紹介されています(冒頭参照)。

コンテントパイプラインのサンプルなので、自作地形へのコード流用はできませんが、アルゴリズムは参考になるかもしれないので、ざっと見てみましょう。


NormalMappingModelProcessor.cs
モデルプロセッサを拡張して法線マップに対応:法線マップテクスチャの存否確認:頂点チャネル関連処理:マテリアル関連処理(NormalMappingMaterialProcessorの呼び出し)

NormalMappingMaterialProcessor.cs
テクスチャ名により法線マップか否かを判定し、法線マップであればNormalMapTextureProcessorを呼び出し、それ以外であれば通常のテクスチャプロセッサを呼び出す。

NormalMapTextureProcessor.cs
法線マップ関連処理


法線マップ以外のテクスチャ登録は、テクスチャプロセッサを呼び出すだけでした。メインプログラム側でもテクスチャを操作している様子はありません。結局、今回のテーマの参考にはなりませんでしたね~。



◎疑問点の確認

サンプル解析を通して私が知りたかった疑問は、「EffectMaterialContentクラスやMaterialContentクラスで登録したテクスチャ情報は、メインプログラム側で読み込む際に、どこにどのように格納されるのか?」という点です。

これは、先の「Effectクラスの中でテクスチャはどのように管理されているのか?」という疑問と一致すると思います。

謎を解くためのキーワードは、マテリアル??



◎XNAのマテリアルとは?

マテリアルとは、日本語で原料や素材といった意味で、3Dの世界では、物質表面の色や質感(ざらざら、つるつるなど)を表現するための情報のことです。

メタセコイアの材質(=マテリアル)は、材質設定画面を見るとすぐにピンと来るのですが、

メタセコイアの材質設定画面
メタセコイアの材質設定画面

XNAの世界でマテリアルと言われても、私にはいまいちピンときません。多分、XNAに毅然とした「マテリアル」クラスが存在せず、言葉が示す実体があいまいだからだと思います。

そこで「XNAでマテリアルと言えば何のことか?」から確認することにしました。



◎BasicEffectのマテリアル

こちらの記事では、5つのパラメータがマテリアルとして紹介されています。XNAのBasicEffectのマニュアルにもそう書かれています。ちなみに、BasicEffectにはTextureプロパティも存在しますが、これはマテリアルに含まれないようです。

余談ですが、Direct3DのMaterial構造体も、これに近いパラメータ構成でした。(項目が微妙に違うようですが…)

しかし、MaterialProcessorクラスやMaterialContentクラスのマニュアルには、上記のようなパラメータは存在せず、テクスチャ関連の情報のみ存在します。

ムムム…この2つの関係は一体??

強引に推測すると、テクスチャ未使用時のマテリアルは前者、テクスチャ使用時のマテリアルは後者ってことなんですかね~??(自信なし)



◎マテリアルとテクスチャの行方は?

Modelクラス以下の、
ModelMeshCollection、ModelMesh、
ModelMeshPartCollection、ModelMeshPart、
ModelBoneCollection、ModelBone、
いずれのクラスにも、マテリアルやテクスチャに関する情報は無さそうです。

ここまで調べた限りでは、テクスチャ情報を格納する場所は、
・BasicEffect.Textureプロパティ
・Effect.Parametersコレクションにパラメータとして追加する
上記以外に見当たりませんでした。



◎メタセコイアのマテリアル

メタセコイアで、複数のテクスチャ(=複数の材質(=マテリアル))を割り当てた3Dモデルを作成し、これをXNAで読み込むケースを想定して考えます。

ModelMeshPart1つにつきEffect1つ、Effect1つにつきテクスチャ1つと仮定すると、メタセコイアで材質を割り当てた単位でModelMeshPartを分割すれば、複数のテクスチャを表示できるんじゃないですかね?

つまり「メタセコイアのマテリアル単位の形状=XNAのModelMeshPart」ってことです。推測ですけど、これなら辻褄が合いますね。



◎次回予告

今回の調査や推測がどこまで正しいのかわかりませんが、とりあえず正しいと仮定して、自作地形に適用する方法を検討します。

スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント

こんにちは

 こんにちは。鳳雛です。
この度、こちらのブログ及びHPにこさせていただきました。
僕の使ったことのないソフトですが、色々研究されてるのですね。僕も色々と覚えている途中です。

 ところで三国志のゲームは、シミュレーションとお聞きしましたが、登場武将等は、もしかしてKOEIのように500人くらいにはなるのでしょうか?

コメントありがとうございます

鳳雛さんこんにちは。
コメントでは初めてですね。今後ともよろしくお願いします。

>僕の使ったことのないソフトですが、色々研究されてるのですね。

まだ駆け出しで至らぬことばかりですが、徐々にレベルを上げていくつもりです。

>僕も色々と覚えている途中です。

お互いに頑張りましょう!

>登場武将等は、もしかしてKOEIのように500人くらいにはなるのでしょうか?

いいえ、第一弾は「荊州争奪戦」のため、荊州戦に参加した武将のみ登場します。ザコ武将はそこそこ多いのですが、有力武将は15人ぐらいです。有力武将はグラフィックが個別、ザコ武将はグラフィックが共通になります。

第二弾は全国区となり、KOEIのように500人ぐらい登場します。(500人分の能力パラメータが既に作成済だったりします(^^;)

BasicEffect関連

同じようなことが気になっている方はやはりいるものですね。結局のところ、XNAで敢えてマテリアルというものを定義するならば、「Effect.Parametersで設定できるもの(テクスチャも含め)全て」という気がします。これは「HLSLでuniformとして与えられるもの」とも言えます。

ただご承知のように、そもそもシェーダの組み方によってどんなパラメータを与えられるかが異なるわけです。例えば「色なしでテクスチャだけのもの」とか「ライト用の色3つとアルファ」だとか、無限に考えられます。「シェーダによってそれぞれ全く構造が違うからこそ、マテリアルというものを厳密に定義したくてもできない」といったところではないでしょうか。

「ModelMeshPartはModelMeshの中で同一のEffectインスタンスを共有する部分集合」というのは、私も同じ結論に至りました。Load<Model>()したModelインスタンスに限って言えば、各BasicEffectインスタンス≒マテリアルと言ってしまってほぼ問題なさそうです。Mesh.Draw()のさいにも同じマテリアルのものを纏めて描画することで効率化を図っていると思われます。

これがModelを用いない形状とLoad<Effect>()したEffectインスタンスとの組み合わせだと、だいぶ話が違って来るようです。なぜなら同じエファクトファイルを何度もLoad<Effect>()してたくさんインスタンスを作りパラメータだけ変えようとしても、Load<Effect>()が同一のEffectインスタンスしか戻さないからです。マテリアルごとに別のEffectインスタンスがあるのでなく、同一のEffectインスタンスに対してパラメータ群(≒マテリアル)を適宜適用してやるイメージです。

はじめまして

yohさんはじめまして。
コメントありがとうございました。


>同じようなことが気になっている方はやはりいるものですね。

同志の方がいてちょっと嬉しいですw
XNAのマテリアルの定義については、私もyohさんと同じ結論に至りました。


>Mesh.Draw()のさいにも同じマテリアルのものを纏めて描画することで効率化を図っていると思われます。

私もそう思います。ModelMeshPart(実体は分割されたインデックスですね)が、モデルの形状ではなくEffectマテリアル単位で集約されているのは意外でしたが、その後Effect切り替えの遅さを実感し納得しました。


>Load<Effect>()が同一のEffectインスタンスしか戻さないからです。

そうなんですか?それは知りませんでした。複数のモデルクラスインスタンスを生成して、その中で同じエファクトファイルをLoad<Effect>()した場合も、同一のEffectインスタンスを返すのでしょうか?


>同一のEffectインスタンスに対してパラメータ群(≒マテリアル)を適宜適用してやるイメージです。

Effect切り替えは時間がかかるので、その方が効率的でパフォーマンスが向上しますね。最近はマテリアルバッチなどの技法を使って、Effect切り替えをなるべく減らすようにしています。

続きです

Load<Effect>()の件、インスタンスを2回ロードして、片方の変数のメンバ文字列をデバッガで変更したところ、もう一方の変数の中身も変更されていたので同一インスタンスで間違いないかと。

>複数のモデルクラスインスタンスを生成して、その中で同じエファクトファイルをLoad<Effect>()
これはカスタムのModelProcessorを用いた場合のお話でしょうか? だとすればそこまではまだ突き詰められていません…。と言うか、デフォルトのModelProcessorだとBasicEffectしか割り当てられないと勝手に思い込んでいたのですが、じつは違ってたでしょうか。

勉強になります

>Load<Effect>()の件、インスタンスを2回ロードして

それなら間違いないですね!同一インスタンスですか~勉強になりました!w


>これはカスタムの

カスタムを想定してました。ちなみに、デフォルトのModelProcessorはまだ使ったことないです(笑)


>デフォルトのModelProcessorだとBasicEffectしか割り当てられない

BasicEffectも内部的にはカスタムエフェクトの一種なので、多分カスタムエフェクトも割り当て可能と思います。…実際に使ったことがないので、推測ですけど。

以下はBasicEffectのソースです。参考まで。
http://creators.xna.com/en-us/utilities/basiceffectshader

MaterialContentが肝?

何度もすみません、凝り性なもので…。

>>割り当てられない
デフォルトのModelProcessorとXNA付属のサンプルモデルいくつかで実験しました。その結果、やはりLoad<Model>()したModel内の各ModelMeshPartインスタンスのEffectプロパティはどれも必ずBasicEffectになってしまうようです。

リファレンスマニュアルによると「デフォルトのModelProcessor.ProcessGeometryUsingMaterial()は常にBasicMaterialContentを戻す」とありますので、デフォルトのModelProcessorは常にBasicEffectを設定すると考えてよさそうな気がします。

もっともカスタムプロセッサを自作すれば「マテリアル構造体にエフェクトファイルネームを埋め込んでおいて、ModelをロードしたらそのカスタムEffectも自動的にロードして設定する」ことは恐らく可能です。たぶんProcessGeometryUsingMaterial()でEffectMaterialContentを戻せばよいのではないかと。

>以下はBasicEffectのソースです。参考まで。
これはいいですね。やっぱり知りたいという人が多かったのでしょうね。

エフェクトは奥が深いですね

>何度もすみません、凝り性なもので…。

いえいえ、とても勉強になって嬉しいですwww


>デフォルトのModelProcessorは常にBasicEffectを設定する

ああなるほど、yohさんのエフェクト割り当てとは、コンテンツパイプライン上でマテリアルのデフォルトエフェクト割り当てを意味していたのですね。
そうですか、デフォルトのModelProcessorはカスタムエフェクトを指定する機能が無いのですね。また1つ勉強になりました。

ちなみに、私はモデル描画時のエフェクトをカスタムエフェクトに差し替えることを想定して話してました。改めて考えると、普通そんなことしないですよねw


>を戻せばよいのではないかと。

仰る通りと思います。今後の参考とさせて頂きます。


>やっぱり知りたいという人が多かったのでしょうね。

私も知りたかった一人ですw
BasicEffectで作成したマテリアルを、このカスタムエフェクトに差し替えてから、中身を少しずつ修正していく…なんてことが出来るのではないかと期待してます。

すみません!

じつはxファイルのMaterialテンプレートにEffectInstanceという子要素を含められるようです。このテンプレートにはEffectFilenameというまさしくfxファイルを指定するためのメンバがありますので、まだ未確認ですが、これを使えばデフォルトのModelProcessorでも(BasicEffectでない)Effectインスタンスが設定されたモデルを読み込めるかも知れません。

大変お騒がせいたしました…。

エフェクトとテクスチャの格納先

>EffectInstanceという子要素

xファイルをXNAにロードする際、ModelMeshクラスのEffectsプロパティに、ModelEffectCollectionクラスとして格納されるように思います。

この時、ModelMeshクラスにはVertexBufferやIndexBufferも同様に格納されると思いますが、テクスチャ情報に関しては格納先が不明です。

TextureCollectionクラスとしてどこかに格納され、エフェクトインスタンスのEffect.Parametersから個々に呼び出されるものと予想して調べたのですが、裏付けは取れませんでした。

テクスチャへのアクセス

BasicEffectならTextureプロパティで取得できますし、EffectならParameters[]に格納されているのではないでしょうか(パラメータ名はfxファイルで指定したもの。2枚以上ならその数だけ)。EffectParameter.GetValueTexture****()で取得できますよ。

ちなみにこないだ教えていただいたBasicEffectのfxファイルでは"BasicTexture"がテクスチャのパラメータ名となっています(BasicEffectなので1枚だけ)。なのでTextureプロパティとParameters["BasicTexture"].GetValueTexture2D()が同じ結果を戻します。

Modelインスタンスの中のテクスチャイメージ

>~で取得できますよ。

それはそのとおりなんですけどね。

Content.Load()で読み込んだModelインスタンスをModelMesh.Draw()で表示できるということは、必要な情報がこの中に全て格納されていることを意味します。頂点情報やEffect情報等は~Collectionクラスで集約管理されているのに、テクスチャだけ集約管理されないのは不自然な気がするんですね。

複数のテクスチャを持つModelインスタンスの場合、テクスチャイメージをメモリ内でどのように格納してるのかな~?と。


>"BasicTexture"が

そうですか~同一パラメータ名を指定すれば同じ結果になると予想してましたが、fxファイルの中身はまだ解析してなかったので初めて知りました。

ちなみに、私の目標はBasicEffectを全てカスタムエフェクトに差し替えて、ボーン情報も内包するというものです。そこまでしないとACL(アニメーションライブラリ)が安心して使えないようなので。

メモリ

アクセス方法が分からないというお話ではなかったのですね。失礼しました。ただブログ主さんの仰る「メモリ内で“どのように”格納しているか」という言葉の意味がちょっとつかめずにいます。

と言うか、そもそもマネージドの世界ですからオブジェクトはみなヒープ上に置かれるわけで、CやC++と違ってメモリ上での配置のコントロールという概念はない気がするんですが。…そういうことではなく?

入れ物と状態

>言葉の意味

わかりにくくてすみません。「どの入れ物(クラス、構造体等)に、どのような状態(個別、配列、リスト等)で、テクスチャイメージを格納すべきか?」という意味です。

1つ例を挙げます。これは後で理解したのですが、インデックスはマテリアル単位に分割した状態でメモリに格納すべきものでした。自作モデルはそれを知らずに1次元配列インデックスで作ってしまったので、後で2次元配列インデックスに作り直しました。

こういうことかな?

Na-7さんの質問の「どう格納するか」というのは、ER図の1対n関係だとか、UMLのクラス図の集約のようなものだとイメージしました。だとすれば、「1つのEffectから見てTextureは0..n個設定されている」と言えると思います。

「テクスチャはあくまで、ベクトルや行列と同じシェーダ定数(XNAでのEffectParameter)の一種」だと見なされているようです。

EffectにはEffectParameterがコレクションとして集約管理されています。で、Textureもそこへ“EffectParameterの一種”として登録されているわけです。なのでわざわざTextureだけのコレクションを作らなかったのだと思います。便利な仕様かどうかはともかく、この辺はどうも、XNAがラップしているDirectXのID3DXEffectインターフェイスのしくみに由来するようです。

TextureCollectionクラスについて

仰るとおり、エフェクトとテクスチャは1対nの関係ですね。TextureCollectionクラスはXNAに実在しますが、エフェクトとは無関係なのでしょうか?

私はXNAからシェーダへ複数のテクスチャをまとめて引き渡す際に、個々のテクスチャをTextureCollectionクラスに格納して引き渡すのかと思ってました。そうすれば、エフェクトパラメータは1つで済みますからね。

でもマニュアルには「Texture オブジェクトを表します」「Item:指定されたサンプラ番号の Texture を取得または設定します 」ぐらいしか書かれてないのでよくわかりません。ネットで検索してもあまりヒットしないので、通常はユーザが利用する類のクラスではないのかもしれませんね。どうもお騒がせしました。

一応、これで一段落?

>TextureCollectionクラス
これはたぶん、GraphicsDevice.Texturesですよ。
手動でも設定出来ますし、恐らくEffect.Begin()によって自動で設定されるんじゃなかったかと。

それではまた。

ありがとうございました!

>これはたぶん、GraphicsDevice.Texturesですよ。

そうですか!ありがとうございます。お陰さまで頭の中がすっきりしました!


>それではまた。

いろいろ教えて頂いてありがとうございました。楽しかったです。

私はMZ-2000からパソコン始めて、その後SEとして働いた経験があるので、yohさんと共通点が多そうな気がします。またよろしくお願いします!

コメントの投稿


管理者にだけ表示を許可する

トラックバック


この記事にトラックバックする(FC2ブログユーザー)



copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。