プロフィール

Na-7

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


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
HLSL描画による自作地形(法線処理後)
HLSLによる自作地形表示
複数テクスチャ化を目指してHLSLの導入を開始。第一段階として、単数テクスチャによる実装を試みた。



◎2つの方式

前回の調査を踏まえて、自作地形を複数テクスチャ化する方法を考えると、2つの方式が思い付きました。

A案
適用するテクスチャ毎に頂点データを分割して地形モデルを作成する。表示時は、分割された頂点データ郡にテクスチャを適用する。(前回の「◎メタセコイアのマテリアル」で推測した方式に近い)

地形作成時のコードは煩雑かつ大幅な改修が必要だが、表示時のコードはシンプル。カスタムエフェクト不要。

B案
頂点データフォーマットにテクスチャ情報を追加し、表示時はその情報を参照しながらテクスチャを適用する。

地形作成時のコードは小幅な改修程度だが、表示時はカスタムエフェクト(HLSL)の作成が必要。



◎選択

A案B案、どちらにすべきか検討します。

改修量:同等?
改修難易度:A案優位
描画速度:A案が僅かに優位?
拡張性、メンテナンス性:B案優位

・描画速度について
B案は「何のテクスチャを貼るか?」をポリゴン毎に確認しながら描画するため、A案に比べると若干遅くなりそうです。但し、全体の描画処理量から察すると、気にすべきレベルではなさそうな気がします。

・拡張性について
例えば「森」地形で火計が使用されて「森の焼け跡」地形に変形する場合、その場所(ポリゴン)だけテクスチャを変更したいのですが、A案の場合、かなり複雑なコードを組むか、地形モデルを再構築する必要があります。
B案の場合、比較的シンプルなコードになります。地形モデル再構築の要否は不明です。(頂点データの値を変更しただけでテクスチャ表示に反映されれば不要)

う~ん…拡張する度にややこしいコードが増えるのは嫌なので、B案にすべきかなぁ?(微妙ですけど)



◎具体化

B案の手順をもう少し具体化すると、

1.カスタム頂点フォーマットを作成し、
  テクスチャ情報(サンプラデータ)を追加する
2.表示時にカスタムエフェクトを呼び出し、
  エフェクトテクニックを指定する
3.HLSLでエフェクトテクニックを記述し、
  指定されたテクスチャで描画する

こんな感じですかね~。

機能的には(HLSLを使わずとも)XNAだけで実現できそうですが、1ポリゴン単位でテクスチャを切り替えるため、速度は著しく低下しそうです。
速度向上のため、HLSLから頂点データ内のサンプラ情報を直接取得して、テクスチャを切り替えます。



◎技術的な課題

技術的には「HLSLからカスタム頂点内のサンプラデータを取得する」ことと、「サンプラデータで指定されたテクスチャを描画する」ことが課題になりそうです。

後者に関しては、前回参考記事内のHLSLのサンプラを増やせば、複数テクスチャに対応できそうな気がします。

問題は前者です。VertexElementUsage.Sampleを使用したサンプルを探そうとしたのですが、全然見つかりません。
B案なんて普通やらないのかなぁ…すごく不安になってきました(ーー;



◎まずは基礎勉強

まずは基礎固めということで、先の「かんたんXNA HLSL編」を「その1」から「その7」まで一通り勉強させて頂きました。

これまで「多分こうだろう」と思っていたことが確信できるようになったり、新たに学んだことも多く、予想以上に良い勉強になりました。これでHLSLも恐くない!…気がするw



◎とりあえずやってみる

まずはカスタム頂点をVertexPositionNormalTextureと同様に作成して、とりあえず1つのテクスチャを表示するHLSLを作成して…あれ?法線はHLSLでどう処理すれば良いのでしょう??
…とりあえず、最初は法線も無視してやってみます。

HLSL描画による自作地形(法線未処理)

おお!とりあえず最初の表示はできましたね!
でも、影が無いので、立体感はありませんね。



◎法線の反映

こちらのHLSLコードを参考に、BasicEffectの環境光(AmbientLight)と平行光源(DirectionalLight)の再現を試みました。

(冒頭図参照)

ふむぅ…地形の形状に沿って影が付いたので、法線がきちんと取得できたことは間違いありませんね。ひとまず成功と言えるでしょう。

BasicEffectに比べるとかなり暗いのですが、鏡面反射光(SpecularColor)などを再現すれば近付くかもしれません。それと、画面全体に細い横線が入っているのが気になりますが、これを解消するのは大変そうなので、当面は無視します。

MapEffect.fx(HLSLサンプル)
(ライトの計算は自信ありませんので御承知おきください)



◎次回予告

BasicEffectの完全再現は大変そうなので、先に複数テクスチャの貼り付けを試みます。
…果たして、このままB案でいけるでしょうか??

スポンサーサイト

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

| BLOG TOP |
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」ってことです。推測ですけど、これなら辻褄が合いますね。



◎次回予告

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

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形16
開発中の自作地形
サンプル地形をやめて全て自作地形に置き換えたが、地表の滑らかさは維持している。



◎似てる?

複数テクスチャファイルの実現に向けて調査していたら、こんな記事を見付けました。

この記事では、サンプラでフィルターを指定することによって、テクスチャのギザギザを滑らかにしています。

これって、サンプル地形と自作地形の見た目の違いに似てるような気がしませんか??

自作地形04の参考元   自作地形04
サンプル地形(左図)と自作地形(右図)


◎違う?

この記事ではHLSLで実装していますが、XNAのマニュアルを見ると、テクスチャフィルタに関する記述があるので、XNAでも実装できそうです。

サンプルコードを探したら、こちらの記事を見付けました。

そこで、このコードを参考に、いろいろ試してみたのですが…どうやっても自作地形の見た目が変化しません。何かやり方が違うのか?それとも、全然関係無い話だったのか?



◎BasicEffectのクローン

試行錯誤を繰り返していたら、ふとある事に気付きました。

「BasicEffectって、クローン作成できるじゃん!」

ということは、サンプル地形のBasicEffectクローンを作成して、自作地形に適用すると…うりゃっ!

自作地形15
自作地形

やりました!自作地形の地表がサンプル地形と同様に滑らかになりました!

これで「サンプル地形と自作地形の見た目の違いは、BasicEffectの違いが原因」ということが証明されました!



◎パラメータの特定

こうなったら、あとはサンプル地形と自作地形のBasicEffectパラメータの値を比較チェックすれば、見た目が違っていた原因が特定できるはずです。
気になる箇所にアタリを付けて探っていくと…あるパラメータに辿り着きました。

this.basicEffect.Texture.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;

自作地形にサンプル地形のBasicEffectクローンを適用すると、見た目滑らかになります。この状態で、上記パラメータをTextureFilter.Noneとすると、見た目ギザギザになります。

ところが、自作地形にサンプル地形のBasicEffectクローンを適用しない状態で、上記パラメータをいろいろ変えても、見た目変化しません。何故~!?



◎ミップマップの生成

この謎を解くため、テクスチャフィルタについて調べていくと、ある仮説が思い付きました。

「自作地形はミップマップが用意されていないので、テクスチャフィルタの効果が表れないのではないか?」

その真偽を確認すべく、メモリ内のミップマップデータにアクセスする方法を調べたのですが、なかなか見つかりません。

そこでミップマップを作成する方法について調べると、コンテントパイプライン内でコードを記述する方法と、コンテントプロセッサのプロパティで指定する方法がありました。

後者の方法で、テクスチャファイルのプロパティ → Content Processor → Generate Mipmaps を True に設定すると…自作地形が滑らかに!

やった!ついにサンプル地形の地表を再現できました!



◎衝撃の事実

この後コードを整理する段階で気付いたのですが、どうやらテクスチャフィルタのデフォルト設定はLinearらしいです。

つまり、今回追加したコードは一切不要だったのです。全部削っても問題無く動きました。ガーン!!

これまで苦労して辿り着いた答えが「プロパティ設定をTrueにするだけ」とは…私にとって衝撃的な事実です…ぐはっ!



◎余談

自作地形にサンプル地形のBasicEffectクローンを適用した状態(滑らか状態)で、

A:this.basicEffect.Texture.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.None;

B:this.basicEffect.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.None;

C:graphics.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.None;

ABCどの設定も全てギザギザ状態になりました。参照先は同じっぽいです。



◎次回予告

というわけで、地表、川、道の3モデル全て自作地形になりました。(冒頭参照)

残る課題「複数のテクスチャファイルを貼り付ける」をクリアすれば、地形モデルを1つに統合できます。あと一息~!

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
DwarfTutorialサンプル添付テクスチャ
DwarfTutorialサンプル添付テクスチャ
複数の絵(テクスチャ)を1枚のテクスチャにまとめた実例。同様の3Dモデルは、他にも多数存在する。



◎テクスチャは統合すべきか?

前回は、パターンテクスチャを別々のファイルに出力しました。これを自作地形に貼り付けようとして気付いたのですが、このままの状態だと、自作モデルに複数のテクスチャを張り付ける必要があります。

それは今の私の技術力では難しいので、1枚のテクスチャファイルにまとめることを考えました。(冒頭の例を参照)



◎メリットと懸念事項

テクスチャファイルを1枚にまとめれば、ファイル管理が楽になります。ゲーム実行中にPCに与える負荷は、複数テクスチャファイル方式と同等でしょう。ツールを改造すれば、テクスチャの一部差し替えもボタン一発でできます。

しかし、この方式には1つ懸念があります。XNAで巨大なテクスチャファイルを扱えるか?という点です。



◎巨大テクスチャファイルの検証

GIMPで巨大画像を作成し、自作地形に貼り付けて試したら、こんな結果になりました。


・8192×8192
 ビルドエラーになる(メモリ不足っぽい)

・4096×4096
 ビルドは通るが'System.ArgumentException' の初回例外発生で落ちる

・2048×2048、1024×1024
 ビルドは通るが'Microsoft.Xna.Framework.Content.ContentLoadException' の初回例外発生で落ちる


ビルドエラーはPCのハードスペック、他のエラーはプログラムによって生じたものと推測します。(XNAの制約ではないと思います)

Contentのエラーはプログラムを改良すれば回避できそうな気がしますが、ArgumentExceptionの回避はちょっと難しそうです(カンです)。



◎結論

開発環境のハードスペックを上げればビルドエラーは出なくなると思いますが、プレイヤーのPCで動かなくては意味がありません。実行環境のスペックはなるべく下げたいので「画像解像度は2048×2048以内とする」と決めました。

今の地形テクスチャは512×512です。現時点でのパターン数は6種類ですが、地形種別が増えると倍々に増加します。
画像を縮小したり、使用するパターンを厳選すれば小さくなりますが、やりすぎると画像品質が劣化します。

全パターンを2048×2048に収めきるなんて、無理…と言うか、その方向で頑張ってはいけない気がします。というわけで、1枚のテクスチャにまとめる方式は諦めます。



◎次回予告

1枚のテクスチャにまとめきれれば、複数テクスチャをやらなくても地形が完成すると思ったのですが…ちょっと甘かったですね~

こうなったら覚悟を決めて、次回から複数テクスチャファイルにチャレンジします!

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
C#とVB.NETの入門サイト
C#とVB.Netの入門サイト
シンプルなサンプルが多く、解説不要で気軽に流用できる。切り貼りして修正すれば作業効率アップに繋がるかも。



◎川の流れ

ちょっとした遊び心と、視覚効果の確認を兼ねて、川の水が流れるアニメーションをやってみました。テクスチャを3パターン用意して一定時間毎に切り替えただけです。古典的な手法ですが、簡単に実装できるのが魅力ですね。

…マップの左上から右下に向かってゆったり流れていくようで、割といい感じです。

できればお見せしたいのですが…さすがにこれだけで動画にするのは気が引けるし、静止画像ではわからないので、今回は見送ります。



◎統合の必要性

前回でサンプル地形モデルと川モデル、道モデルを合成し、見た目は良くなりました。しかし、地形モデルを3つも表示しているので、マシンへの負荷も高くなりました。

このままだと、地形を1種類増やす毎に地形種別モデルを1つ追加することになり、マシンに負荷がかかりすぎます。

そこで今回は、地形種別モデルを1つに統合し、マシン負荷を軽減する方策を検討します。



◎どのテクスチャを貼るべきか?

統合する場合、カラーマップの水色ピクセルに該当する場所に水のテクスチャ、黄色ピクセルに該当する場所に道のテクスチャを貼りたいわけですが、テクスチャは(頂点ではなく)面に貼り付けるものです。

面とはポリゴンの面であり、ポリゴンには3つの頂点が含まれます。頂点はカラーマップの1ピクセルに該当するので、3つの頂点の色が全て同一とは限りません。頂点の色が異なる場合、どのテクスチャを貼れば良いのでしょうか?

結論から言うと、頂点の色の組み合わせに相応するテクスチャを別途用意して対応します。



◎色の組み合わせパターン

頂点の色の組み合わせパターンは、以下の通りです。

白白白  水白白  黄白白
白白水  水白水  黄白水
白白黄  水白黄  黄白黄

白水白  水水白  黄水白
白水水  水水水  黄水水
白水黄  水水黄  黄水黄

白黄白  水黄白  黄黄白
白黄水  水黄水  黄黄水
白黄黄  水黄黄  黄黄黄

このうち、白頂点は盛り上げないので、白頂点を含むパターンは、全て無視できます。(他のパターンで代用可能)
また、水と黄が混在していないパターンは、従来の「水のテクスチャ」「道のテクスチャ」だけで表現できるので、無視できます。
よって、テクスチャが新たに必要となる頂点パターンは、以下の6種類です。

水水黄  黄水水  黄水黄
水黄水  水黄黄  黄黄水

テクスチャが新たに必要となる頂点パターン



◎切り貼り作業の手間

パターンテクスチャは、CGツールで切り貼りすると作成できます。

今回は大した数ではありませんが、今後地形種別が増えると、組み合わせが倍々に増えていきます。さらに、今後何度もテクスチャを差し替えることを想定すると、膨大な手間が懸念されます。
やはりこの作業は、自動化しておくべきでしょう。

「こういった作業を一発でやってくれるツールがあるんじゃないか?」と思って探そうとしたのですが…すぐに諦めました。
画像ツールやらフィルタやらスクリプトやらが無数にあって、どれをどう組み合わせれば目的を達成できるのか、見当も付かないからです。

1つ1つ機能を調査したり、ツールやスクリプトを修得したり試したりする手間を考えると、作った方が早そうです。



◎開発環境は?

パターンテクスチャ自動作成ツールを自作するとして、何で作るかなぁ…。

XNAは却下。画像加工ツール作成に一番向いてません。
VB6なら速攻で作れそうですが、将来性が無いのでメンテナンスが心配。せめてVB.Netなら良いのですが、これはあまり使ったことない…いっそのことExcelVBAとか?

…で、結局VC#にしました。XNAと同じ環境(XNAはVC#のテンプレート)だし、これを機に少しでも覚えておいて損はないかと。ちなみに、XNAもCも去年始めたばかりの初心者です。たはは…(^^;



◎ツールの作成

というわけで、こちらの記事や冒頭のサイトを参考に、パターンテクスチャ自動作成ツールを作成します。

パターンテクスチャ自動作成ツール

…完成しました。VB並みに簡単ですね~。

XNAでGetPixelとかシリアライズとか苦戦して「C言語は何をするにも面倒臭い」という印象があったので、こんなにあっさりできるとは思いませんでした(笑)



◎次回予告

パターンテクスチャの準備が完了したので、次回は自作地形を統合する予定です。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形14
開発中の自作地形
道モデルを合成し、川幅を細くした。自作地形は独特の方式で作られており、川幅や道幅を簡単に変更できる。



◎道モデルの作成

道モデルを作成するために、まずカラーマップを修正します。カラーマップの解像度を落とした際に、中間色になった部分は色の判別が難しくなるので、中間色を全て1色で塗り直します。


次に、プログラムを修正します。モデル作成関数に引数を追加してテクスチャを指定可能とし、あとは川モデルと同様にモデル作成関数を呼び出すだけです。


最後に、テクスチャを用意しますが…道のテクスチャって、どんな感じがいいですかね?古代中国の街道と言えば、石がゴロゴロしてるイメージかなぁ?

…むむ、実際に貼り付けると、スケール(縮尺)が一致しません。では、スケールを指定できるよう改造して…えいっ!

石の道モデル

あらら…遠くから見ると、灰色のボツボツになってしまうんですね。石ゴロゴロはやめるか…砂利はどうかな?

道モデル

さっきよりはマシかな?…まぁ、テクスチャは後で簡単に差し替え可能なので、とりあえずこれでいきますか。



◎道モデルの合成と幅調整

では、合成しましょう。と言っても、普通に表示するだけなんですけど。

自作地形13

ふ~む…何と言うか、ベタッとした印象ですね。もう少し何とかならないかな?
ちょっとこの数値をいじると…?

(冒頭参照)

おお、川幅や道幅が細くなって、繊細な印象を受けますね!
自分で言うのも何ですけど、256×256のカラーマップから自動生成したとは思えません。



◎問題と解答

ここでちょっと問題。
何の数値をいじったか、皆さん予想できますか?





正解は「へこみ系数(凹系数)」です。

川モデルや道モデルでは、カラーマップ該当色の場所をちょっとだけ高くしますが、それ以外の場所はちょっとだけ低くします。低くする度合いが「へこみ系数」です。
頂点の周囲がへこむと、頂点がさらに鋭く細くなります。



◎キレギレ現象について

川幅や道幅を細くすると、さらに途切れやすくなります。
このキレギレ現象について、補足します。

道のキレギレ

上図では、手前の道がキレギレになっている所があります。カラーマップ内で、斜め1ピクセルで繋がっていると、こうなります。

逆に言うと、縦横1ピクセルか、斜め2ピクセルならば、キレギレになりません。奥の道が斜めでも繋がっているのは、そのためです。


今後、カラーマップの解像度を上げてから修正する予定ですので、現時点でのキレギレ現象は気にしないでください。



◎次回予告

このブログで翌日更新なんて、珍しいですね~。
いつも何か「思わぬ所でハマる」んですが、今回は珍しく順調でした。こんな日は年に数回じゃないかな~?(笑)

次回は、川モデルと道モデルの統合について検討します。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形12
飛行テスト中の画面
地形モデルの高さに合わせて城モデルを配置した。飛行テストにより目視確認中の画面。



◎座標系の調整

前々回のマップ上のユニットは、見た目のイメージを掴むため強引に配置したのですが、実は空中に浮いているので、カメラの角度を変えるとおかしくなります。

そこでユニットの座標系をマップの座標系に合わせるよう修正します。細かく記述すると、こんな感じです。

1.マップ用のビューカメラを共通クラスに移植
2.ユニットのビューカメラを共通クラスに変更
3.マップ用の飛行テスト関連処理を共通クラスに移植
4.マップオブジェクトのビューカメラを共通クラスに変更
5.マップ上の高さを取得してユニットを配置
6.マップ上の高さを取得してマップオブジェクトを配置
7.ユニットとマップオブジェクトの大雑把な位置調整

自作地形11

ビューカメラを共通化し、全モデル表示状態での飛行テストを可能としたので、戦場となる「箱庭」が固まってきた感じがします。

あとはユニットやマップオブジェクトを順次追加していけば良いですね(^^)



◎重いな~

ブログではあまり触れていませんが、実はユニットを多数表示した頃から重い(遅い)と感じていました。
(初期化は早いが、ゲーム実行中の処理が重い)

重い要因は複数考えられますが、どの要素がどのくらい影響するか判らないと、効果的な対処に繋がりません。
影響度は様々な条件で変動するので、条件がある程度整うまで無視してきました。

しかし、ユニットを含めた飛行テストが可能になると、改めて「重いな~」と感じました。座標系やサイズ等の条件もある程度固まってきたので、これを機に一度調査しようと思い立ちました。



◎調査目的

高速化の案は幾つか考えていますが、その1つに、「マップ種別毎にモデルを用意する」というのがあります。例えば、同じ城モデルでも、全体マップ用と地域マップ用として別々に用意する、ということです。全体マップ用のモデルは小さく表示されるので、ポリゴン数を減らすことが可能です。

今回は、マップ種別毎のモデルを作成する際に有効な要素を特定することが目的です。例えば、

・モデルの数を半分にする
・ポリゴン数を半分にする
・テクスチャ数を半分にする
・表示サイズを半分にする
・モーション稼働部を半分にする

上記の処置は、それぞれどれぐらい効果があるか?を知りたいわけです。



◎あれ?

オートパイロットの飛行プログラムを作成し、A地点からB地点までの所要時間を計測。さらに条件を変更して飛行テストを実施すると…最初と同じ時間でした。
「あれ?」

…ああなるほど、処理落ちではなく、フレーム落ちだったのですね。表示が飛ばされるだけなので、ゲーム内の所要時間を計測しても意味がありません。

とりあえずCPU使用率をチェックすると、サンプル地形か自作地形どちらか片方を表示するだけで(Core2CPUの片方の)80%を超えました。あまり参考になりませんね~。



◎自問自答

フレーム落ちなんだから、秒間フレーム数をチェックしないとダメか。でも、フレーム数って思いっきりグラボ依存でしょ?「効果のほどはグラボ次第」という結論になるなら、フレーム数を計測しても意味無いじゃん…。

ああ、去年も同じ疑問を抱いて、同じ結論に至った気がする…何やってんだか(>_<)



◎次回予告

テストパターンをきっちり作ってから意味無いことに気付いて、ちょっとガックリきました。

…まぁ、こんなこともありますよね?
気を取り直して、次回は道モデルを作成します。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
面法線加算方式
面法線加算方式による自作地形
サンプルと同じ法線の値を設定することに成功したが、見た目はサンプルと同様にならなかった。



前々回のテーマ「法線」の続きです。法線シリーズ決着編!


◎新しい計算式

前々回で、自作地形とサンプル地形の法線が異なることを認識し、サンプル地形の法線式を求めようと試みましたが、果たせませんでした。

その後、seb2008さんから、コメントで法線の計算コードを紹介して頂きました。そのコードをXNAに移植しても計算結果は一致しなかったのですが、その時に新しい発見がありました。

私は今まで「右の頂点へのベクトル」と「上の頂点へのベクトル」を元に計算していたのですが、そのコードは「左の頂点から右の頂点へのベクトル」と「下の頂点から上の頂点へのベクトル」を元に計算していました。
なるほど、注目頂点を中心とする法線ですね!



◎一致しません

早速改修して新計算式を試そうとしたのですが…改修中に「あ、この方法はサンプルと一致しないな」と気付きました。
一通り修正して結果を確認すると…やはり一致しませんでした。

一致しない理由は、次のように推測できます。
「サンプルはModelProcessorという部品(ブラックボックス)の中で法線を計算しているが、この部品は一般モデルを対象に汎用的に作られている。今回の計算式は、地形モデル専用の計算式であり、他の一般モデルでは通用しない。よって、ModelProcessorは別の計算式で法線を算出しているはずである」



◎ちょっと待てよ?

一般モデルにも通用する法線の求め方と言ったら、やはりその頂点を含む全ての面法線から算出するしか無いのでは?
でもそれは以前試したけど一致しなかったんだよなぁ…何か間違えたのか?

そう思ってExcelを見直すと…重大なミスに気付きました!
頂点の向きを間違えていたのです!!

ポリゴンの向き

上図を見ればわかると思いますが、1つの頂点に隣接するポリゴンは、8個ではなく6個でした。



◎一致しました!

というわけで、修正版は以下の通りです。
(ポリゴンの向きによって、2パターンあります)

隣接する全ての面法線を求め、頂点の法線を算出する(修正版パターンA)(PDF形式)

隣接する全ての面法線を求め、頂点の法線を算出する(修正版パターンB)(PDF形式)

やりました!パターンBがついにサンプルの値と一致しました!散々頭を悩ませてきたので、数値が一致したのを見た瞬間、思わず感動してしまいました(笑)

「結果から計算式を逆算するというプロセス自体に問題があるのでは?」と不安になったりしましたが、結果が出せて良かったです。きっかけを作って下さったseb2008さん、どうもありがとうございました!



◎見た目は変わらず

サンプルの法線計算式が解明できたので、自作地形に適用しました。(冒頭参照)
…あれ?見た目変わらないですね。どっか間違えたかな?法線の値を出力して確認しましょう。

自作地形の頂点データ(面法線加算方式)(PDF形式)


…出力した法線の値が、サンプルと一致しました。正しくプログラムできています。

法線の値が一致するのに、見た目が違うってことは…エフェクトですね?私にはもうそれしか考えられません。



◎次回予告

結局「見た目の違いは法線によるものではない」という確認にしかなりませんでした。でもまあ、原因を1つ絞り込めたわけですし、私自身のスキルアップに繋がったので、良かったと思います。
もう法線なんて恐くない!(笑)

ちょっと前後しますが、次回は前回の続きになります。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
川モデル合成01
川モデル合成画面
地表モデルに川モデルを重ねて川を追加した画面。
グレースケールマップとカラーマップから自動生成している。



◎地形種別毎にモデルを作成する理由

サンプル地形(HeightmapCollisionの機能流用版)は、グレースケールマップから地形の高さを取得して、3Dモデルを自動生成したものです。
地形の形はこれで満足できるのですが、このままだと地表のテクスチャを1種類で埋め尽くすことしかできません。

そこで、グレースケールマップの他に、カラーマップも用意して、地形種別毎のテクスチャを反映させる、というのが目標です。

バンプテクスチャマップ256   カラーマップ256
グレースケールマップ(左)と地形種別カラーマップ(右)

しかし1つのモデルに複数のテクスチャを張り付けることを(ツールを利用せずに)プログラムだけで実装するのは、今の私の技術力では少し敷居が高いので、最初は地形種別毎に複数の地形モデルを作成し、それらを合成する(重ね合わせる)方法で実装します。

この方法は、見た目が良くなる(後述)反面、地形種別が増える度に地形モデルが増えていくので、PCに余分な負荷がかかります。ベストな方法ではありませんが、まずは手軽な方法で画面に表示し、どんな感じになるか確認するのが狙いです。



◎カラーマップの縮小

最初は自作地表モデル(地表が芝テクスチャの自作地形)と地形種別モデルを重ねるつもりでしたが、「どうせ重ねるなら、今はサンプル地形の方がいいんじゃない?」ってことで、サンプル地形モデルと川モデルを重ねることにしました。


以前書いたように、私のPCではグレースケールマップの解像度を256×256より大きくすると、エラーになります。
多分、グラボの性能が低くて、バッファを充分に確保できないことが原因だと思います。

この問題は、少ないバッファでも動くようにプログラムを改造すれば解決できるかもしれませんが、そのテーマは後回しにして、地形種別モデルの作成を優先します。

というわけで、グレースケールマップの解像度に合わせて、カラーマップの解像度も256×256に縮小しました。



◎川モデルの作成

地形種別モデルの考え方は簡単です。
地形を作成する際に、カラーマップの色を確認し、特定の色であれば少しだけ地形を高くして、それ以外の色であれば低くします。

川モデル

これが川の地形種別モデルです。見た目には判りませんが、カラーマップの水色に相当する部分だけ、少し高くしています。



◎場所も形も想定外?

しかし実際に重ね合わせようとすると、川モデルは想定箇所に浮かび上がらず、想定外の場所に想定外な形が浮かび上がりました。
「色の取得に失敗したのか?どこか判定がおかしいのか?座標がずれているのか?…」
心当たりを1つ1つ潰していったのですが、値はどれも想定通りでした。にもかかわらず、想定通りに表示されないのは何故でしょう?

…かなり悩まされましたが、意外な事実が判明しました。今回プログラムした部分に問題は無く、画面表示も正しかったのです。

・地形モデルが半分しか生成されていなかった
・カラーマップ縮小時に、色が想像以上に変更されていた

この2点に気付いていなかったため、場所も形も想定外のものが表示されて、おかしいように見えただけでした。

地形モデルが半分だけだったのは、以前インデックスバッファを修正した際に、頂点バッファサイズを修正し忘れていたのが原因でした。

それにしても、地形が半分という事実に今まで気付かないなんて…お恥ずかしい限りです。



◎地形モデルの合成

合成…と言っても、特別なことは何もしません。単に2つのモデルを普通に表示するだけです(笑)
では、新しい地形と、昔の地形を比較してみましょう。
(フォグ設定は外しています。また、ユニットの座標系も適当ですので、その辺は気にしないでください。)

川モデル合成02   南陽郡地域図川湖付加04
新しい地形(左)と古い地形(右)

いかがでしょう?
人によって意見が違うかもしれませんが、私は新地形の方が良いと思います。川の流れが切れ切れなのが、航空写真っぽくてリアルに感じます。


さらにアップにしていくと、こんな感じです。

川モデル合成03

アップにしていくと徐々に苦しくなってきますが、これぐらいならまだ耐えられるレベルじゃないでしょうか?

傾斜面を見て頂くとわかると思いますが、今回の「重ね合わせ手法」だと、傾斜面の川は必ずしも四角形にならないのが特徴です。
(「1つのモデルにテクスチャを複数貼る手法」だと、水際のラインがもっとカクカクするかも?)

ちなみに、平面に流れる川がカクカクするのは、どちらの手法も同じです。もっと細かく表現したい場合は、バッファ問題を解決して、マップの解像度を上げる必要があります。



◎次回予告

実は今回は大した話ではなくて、前回までの基礎的な勉強が大切です。…と、頭ではわかっていても、見た目が変わらないと進展してないように見えるので、少し焦っていましたが、今回ようやく見た目が変わったので、少しホッとしました(^^)

今後は、こんな感じで考えています。簡単なものはサクっと終わらせたいですね~。
(大体思い通りにならないんですけどね(^^;)
・座標系を合わせる
・道モデルを追加する
・城モデルの位置を修正する
・バッファ問題を解決してマップ解像度を上げる
・複数テクスチャを実現する

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
物理のかぎしっぽ
物理のかぎしっぽ
共同執筆体制で構築された理数系解説サイト。初心者向けに図入りでわかりやすく解説している。



◎頂点フォーマットの項目順序

最初はVertexPositionNormalTextureでサンプル地形の頂点データ取得を試みましたが、出力結果を確認すると、法線とテクスチャ座標の値が入れ替わっているようです。そのまま読み替えることも可能ですが、一応カスタム頂点フォーマットを定義して再取得したら…推測通りでした。

データの項目数は同じでも、項目順序が異なると値が入れ替わっちゃいますね。危険性は覚悟してましたが、ホームページのやり方は、ちょっと強引過ぎたかなぁ?先頭はPositionから始まることが多いので、いいやり方だと思ったんですけどね…。



◎頂点データの格納順序

サンプル地形の頂点データのxz座標を確認すると、格納順序が不規則であることに気付きました。自作地形はイメージ通り直線的に格納されてました。

サンプル地形の頂点データ(PDF形式)
(後半の表は、後で使います)

自作地形の頂点データ(PDF形式)

サンプル地形の頂点データが何でこんな順番で格納されているのか不思議ですが、モデル表示時の見た目には影響しないと思うので無視します。



◎もう一度ベクトル

自作地形とサンプル地形の頂点データの値を比較したら、法線データが異なることがはっきりしました。では、サンプル地形はどのような計算をしているのでしょうか?

「値が取得できたのだから、逆算して計算式を導くことはできないか?」と思ったものの、そもそもベクトルの商(割り算)って可能なんでしたっけ?

昔はベクトル得意だったはずなんですが、20年経った今となっては全然覚えてません。(^^;
仕方がないので、冒頭のサイトで再勉強しました。


…ははぁ…外積ってつまり法線のことですね。やっと理解しました。あれ?ベクトルの商は無いの?それじゃ逆算できないなぁ。う~ん、どうしよう…。



◎2組のベクトルから法線を求める

1つの頂点に隣接する頂点は、上下左右で4つ、斜めを含めると8つあります。

記憶違いかもしれませんが、昔どこかで「斜めを組み合わせると良い」という記事を読んだような気がするので、サンプルは斜めの頂点を使って計算してるんじゃないかなぁ…。

そう思って適当な組み合わせを試したら、法線の値は変化するものの、サンプルの値とは一致せず、見た目もサンプルに近付いた気がしません。

考えてみると、8方向のうち2方向を組み合わせるパターンは8×7=56通りあります。いちいちプログラムを修正実行するのが面倒になってきたので、最後はExcelで一括計算しました。

2組のベクトルから法線を求める(PDF形式)

組み合わせ可能なパターンを総当たりで算出し、サンプル地形の法線に一致する値を探したのですが、存在しませんでした。あらら…。

つまり、2組のベクトルから単純に算出したのではない、ということですね。算出した値をさらに補正したか、3つ以上のベクトルを利用した可能性が高そうです。



◎8組の面法線から頂点法線を求める

もし3つ以上のベクトルを利用するとしたら、やはり全方向じゃないでしょうか?

しかしそれを求める計算式に自信がありません。全部足して正規化すれば良いような気がしますが…。

一応こちらの記事で確認したら、考え方は間違っていないようなので、Excelで算出してみました。

隣接する全ての面法線を求め、頂点の法線を算出する(PDF形式)

…サンプル地形の法線とは一致しませんでした。え~これも違うの?



◎次回予告

結局今回は数学の復讐で終わってしまいました。一応法線の考え方は理解したつもりですが、サンプルの計算式を解き明かせなかったので、いまいち自信が持てません。

ちょっと行き詰ってきたので、見た目の違いは保留にして、先に川モデル作ろうと思います。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形08   自作地形05の参考元
自作地形とサンプル地形(テクスチャ無し)
並べて比較すると微妙に違う。この状態では悪くなさそうだが、テクスチャを貼ると自作地形は見劣りしてしまう。



◎何が違う?

自作地形とサンプル地形の違いは何か?と、エフェクトや法線を変えたりコードを再比較したりしましたが、どうしてもわかりません。

テクスチャ無し状態で違いがあるってことは、やっぱり法線かなぁ?



◎頂点データの取得

このままではラチがあかないので、ついに頂点データの解析に踏み込むことにしました。ちょっと難しそうなので、気後れしてましたが…でも、やると決めたからには、前向きにやらないとね!

まずVertexBufferのマニュアルを見ると、GetDataというメソッドがありました。これで頂点データが取得できそうですが、適当にやってもなかなか上手くいきません。

ネットで調べると、「ReadOnlyで取得できません」なんてが…ああ、昔のバージョンでした。

コンテントパイプラインでデータ取得するパターンが多いのは、この名残かもしれません。昔は皆さん苦労されてたんですね~。

このコードを少し手直ししたらXNA3.0で動いたので、これを足掛かりに解析を進めます。



◎GetDataの第二引数

自作地形とサンプル地形の頂点データを比較する場合、同一座標の頂点でないと意味がありません。しかし自作地形の外周頂点はわざと法線を加工しているので、内側の頂点データを取得する必要があります。

そこでGetDataの第二引数(startIndex:コピーを開始する配列要素のインデックス)に内側のインデックス番号をセットすると、何故か想定外の動きをします。おかしいな~?

この謎は現在も解決していないのですが、この謎を追いかけているうちに、色々なことがわかってきました。



◎GetDataの解説記事

VertexBuffer.SetDataの使い方やサンプルを掲載した記事はネット上に多数ありましたが、それに比べるとGetDataの解説記事は少ないようです。

衝突判定やデバッグのためにGetDataを覚えたいと思う機会は多そうなのに、何故かな~?と不思議に思っていたのですが、その理由が判りました。

GetDataを正しく使うには、SetDataの知識が不可欠であり、SetDataの知識があれば、GetDataは簡単に使えるはずだから、GetDataは解説不要、というわけです。


でも、衝突判定やデバッグのために「とりあえず頂点データを取得したい」という初心者は私だけじゃないと思うので、そんな人向けの技術資料「3Dモデルの頂点データの取得」を作成しました。

初めに紹介している「簡易取得サンプルコード」は、頂点データフォーマットを決め打ちして強引に取得を試みます。
結果に満足できればそれで良し、ダメなら複雑なコードを追加する…という流れで記述しています。



◎次回予告

デバッグ目的で現状を把握したいだけだったのに、記事の都合上、カスタム頂点データフォーマットまで作成するハメになりました。お陰でいい勉強になりましたよ(笑)

次回は頂点データの内容を解析する予定です。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形10
自作地形モデル
自作地形モデルの最新状態。HeightmapCollisionに近付いてきたが、まだ表面の質感が違う。



◎テクスチャの継ぎ目

テクスチャの継ぎ目(タイル張りの境界)がおかしい問題は、テクスチャ座標の問題でした。

「テクスチャ座標は0~1で指定する」という基本に従って、わざわざ整数部分を除外していたのですが、この除外処理をやめたら境界も綺麗に表示されました。

TextureAddressModeが関係しているのかと思いましたが、今回はデフォルト(設定無し)でタイル張りになりました。



◎エフェクトの追加

テクスチャが設定できるようになったので、エフェクト設定を追加したら、実行時に例外エラーで落ちました。予め設定しても、表示時に設定しても、同じ現象になります。

何か他の描画処理とバッティングしてるのかと思って、ACLやSpriteBatchなどを片っ端からコメント化してみましたが、現象は変わりませんでした。何なんだよ一体…。

そんなこんなで丸1日唸ってましたが、ソーサリーフォースを見直してようやく気付きました。ライトを追加する場合は、頂点データに法線(方向)を追加する必要があるのです。

アルゴリズム参考元のHeightmapCollisionでは、ブラックボックス(ModelProcessor)の中で処理されているらしく、表記上それらしいコードが無いので、なかなか気付けませんでした。



◎法線の問題

というわけで、頂点データに法線を追加し、ライトやフォグを設定しました。

自作地形04

あれ?全然綺麗じゃないですね。HeightmapCollisionと同じエフェクト設定をしたつもりなんですけど、何が違うのでしょうか?

…どうやら、法線の問題らしいです。ネットで地形作成の記事を見ると「法線マップ」という単語が目に付きます。
そうか~全部真上に向けただけじゃダメなのね(爆)



◎法線って何?

「法線」を検索すると、「ある平面に垂直な直線」とあります。しかし、XNAでは法線を頂点データに設定します。頂点の法線って何?

今回は1つの頂点につき8つの面が接合してるから、8つの法線の共有値を設定しろってことかなぁ…うわ~面倒くさ~ブツブツ…

…ん?これって周囲8つの頂点ベクトルを足して単位ベクトルに直せば良いのでは?

自作地形06   自作地形07

あちゃ~、ダメダメですね。
法線が逆転して面の向きが逆転してしまったのが左図、それを強引に補正したのが右図です。(影をわかりやすくするため、白いテクスチャに差し替えています)

法線によって見た目が変化することはよく分かりましたが、計算式の求め方は根本から間違ってる気がします。



◎法線の設定

というわけで、こちらの記事(後半にDirectX用法線マップ計算式の解説があります)を参考に、法線の計算式を作り直しました。
2つのベクトルの外積だけでいいって本当かな~?そもそも外積って何?(爆)

自作地形08   自作地形09

おお!綺麗に表示されました!理屈はいまいち理解できていませんが…。

ちなみに、左図は右頂点と上頂点へのベクトル、右図は右頂点と下頂点へのベクトルで計算したものです。
法線を変えただけで色まで変化するなんて不思議ですね。
光の反射角度によって色が変化するということでしょうか?



◎次回予告

法線って意外と奥が深いですね。見た目がこんなに変わるとは思いませんでした。

ともかくこれでHeightmapCollision完全再現だ~!
…と思ったのですが、テクスチャを貼り直したら、地表の質感が違うことに気付きました(冒頭図)。
まだ何かあるのか~!

次回こそは完全再現を果たして、川モデルの作成に進みたい所ですが…何が違うのかなぁ?

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

| BLOG TOP |

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