乗算済みアルファとは? その2: コンポジション

前回の投稿からものすごーく間があきましたが、乗算済みアルファの話がTwitterの方で盛り上がったので、思い出したように続きを書いてみます。 前回は今まで多く使われてきた補間アルファの問題とそれを解決するための乗算アルファの紹介をしました。今回は乗算済みアルファの真骨頂である半透明を使ったコンポジションを紹介します。 コンポジションの使い道 レースゲームでは、ゲーム内で複数の車を購入でき、さらに購入した車の各パーツを変更することができるという機能は一般的なものです。中には自分で描いた絵を車に張るなんて言うこともできるものもあります。こういったレースゲームでは、購入した車の一覧はガレージメニュー内でサムネイル表示され、車を選択すると3Dモデルが読み込まれ、自分がチューンナップした車のモデルを見ることができます。 では、このサムネイル画面はどうやって表示するのでしょうか? こういった3Dモデルをカスタマイズできるゲームでは、あらかじめサムネイル画像を用意するということはできません。なぜなら、その組み合わせは膨大な数になってしまうのと、ユーザーが描いた絵までは用意することはできないからです。そこで良く用いられるのが、3Dモデルを変更した時にセーブデータ領域などに3Dモデルをレンダリングした結果をサムネイル画像として保存し、それをメニュー画面で使用するという手法です。 単に矩形型のサムネイルを用意するだけだったら問題は無いのですが、このサムネイル画像をビルボードとして使い、メニュー画面の背景の上に重ね合わせて描画したい場合、例えば車のボディ部分のような不透明部分は不透明に、車のウィンドウ部分のような半透明部分はメニュー画面が透けて見えたりするといった重ね合わせ処理をコンポジション(Composition、日本語で「合成」)と呼びます。 コンポジションの基本 コンポジョン処理をする場合の基本として、描画するオブジェクトA,B,Cがあった場合、以下の式が成り立たないといけません。 A + B + C = (A + B) + C = A + (B + C) この式のA+B+Cという部分はオブジェクトA,B,Cの順に描画するという意味で、(A+B)+CはAとBをまとめて描画した結果を描画した後にCを描画、A+(B+C)はAを描画した後にBとCをまとめて描画した結果を描画するという意味になります。言い換えると()で囲まれたオブジェクトは別のレンダーターゲットに描画し、そのレンダーターゲットの描画結果を他のオブジェクトの描画と合成(コンポジット)できるということです。もしくは前述のレースゲームの中のサムネイル画像がカッコ内の部分に相当します。 結論から言うと、上記の式は補間アルファでは成り立たず、乗算済みアルファでは成り立ちます。つまり、補間アルファではできなかったコンポジションが乗算済みアルファではできるということです。 実際に上の式に補間アルファと乗算済みアルファのブレンディング計算式を当てはめると証明できるのですが、長くなるし、読んでもつまらないし、本題から外れるので、ここでは割愛します。 コンポジション比較 では、実際に乗算済みアルファと補間アルファでコンポジションした場合の結果を見比べてみましょう。まずは、レンダーターゲットを使わずに背景を描画した後に赤い不透明の四角形、半透明の緑色の四角の順に描画してみましょう。 乗算済みアルファ、補間アルファ、どちらも同じ結果になっていますね。 では、次に赤と緑の四角形をレンダーターゲットへ描画し、その結果をテクスチャとして使って背景を描画した後に描画してみましょう。 補間アルファを使った方は緑の半透明部分がより薄くなっており、不透明であるはずの赤い部分も半透明になってしまっています。対照的に乗算済みアルファの方は全く同じ描画結果となっています。つまり、補間アルファではコンポジッションが上手くいかなかったのが、乗算済みアルファではコンポジションができるということです。   XNA 4.0でコンポジション処理 では、実際にXNA 4.0でコンポジション処理をする時にどんなコードを書くのか見ていきましょう。 まずは、コンポジション用のレンダーターゲットの生成と、そこへ描画するコードです。通常のレンダーターゲットを使った描画と殆ど同じものですが、ここではColor.Transparentでクリアするのがポイントとなっています。このTransparent(透明色)はRGBA値が(0,0,0,0)になっています。 // コンポジション用のレンダーターゲットの生成 RenderTarget2D layer = new RenderTarget2D(GraphicsDevice, 1280, 720); // **** コンポジション用のレンダーターゲットへの描画 **** // レンダーターゲットをグラフィクスデバイスへ設定する…

0

続・簡単(かもしれない)日本語表示

以前、カスタム・コンテント・プロセッサーを使って日本語表示する方法を紹介しました。 XBLIGやWindows Phone 7に配信することを考えてゲームを作る場合、カスタム・コンテント・プロセッサーを作ることが殆どなので、この方法でも問題無いのですが、初めてXNAをさわり始めた人や、ちょっとしたサンプルを作るときに 「ようこそ、XNAの世界へ♪」 と、いった一文を表示するだけのプログラムなのに、カスタム・コンテント・プロセッサーを使うのは初心者には難易度が高いし、プロジェクトが複雑になってしまいます。 そこで今回はカスタム・コンテント・プロセッサーを使わずに日本語表示をする方法を紹介します。 CharacterRegionsを手動で変更する XNAで文字を表示する場合、プロジェクトにSpritefontファイルを追加しますが、このSpritefontファイルには使用するフォントの種類やサイズ、そしてテクスチャへ変換する文字を指定できるようになっています。この文字の指定はファイルの最後の方にあるCharacterRegionsエレメントで行います。Spritefontを追加した場合、あらかじめ英数字のコードが指定されています。 <CharacterRegions> <CharacterRegion> <Start>&#32;</Start> <End>&#126;</End> </CharacterRegion> </CharacterRegions> この中のStartとEndエレメントに使用する文字の開始と終了文字コードをユニコードで指定されています。 CharacterRegions内にはCharacterRegionエレメントを複数宣言できるので、ひらがなを表示したい場合、ひらがなのユニコードはこうなっているので、以下の様なCharacterRegionを追加します。「&#x番号;」と言うのはXMLファイル内で16進数を指定する方法です。 <!– ひらがな –> <CharacterRegion> <Start>&#x3041;</Start> <End>&#x3096;</End> </CharacterRegion> カタカナや全角英数字なども同様にして追加することができます。以下はそれぞれのユニコード表PDFへのリンクです。 ひらがな: http://www.unicode.org/charts/PDF/U3040.pdf カタカナ: http://www.unicode.org/charts/PDF/U30A0.pdf 全角英数: http://unicode.org/charts/PDF/UFF00.pdf 全角記号(全角スペースや句読点など): http://www.unicode.org/charts/PDF/U3000.pdf この方法でひらがなやカタカナといった、あらかじめ文字コード領域がハッキリしているものを追加することができます。 では、漢字の場合はどうでしょう?ユニコードではCJK、つまり中国語、日本語、そして韓国語の文字が混合して定義されているので、ひらがなと同じように指定することはできないし、コード表から一文字毎にコードを探し出すのは現実的ではありません。 実はSpritefontファイルには直接文字を指定することができます。例えば「日本語」という文字を表示したい場合、以下のようにして表示したい文字を追加することができます。 <CharacterRegions> <CharacterRegion><Start>日</Start><End>日</End></CharacterRegion> <CharacterRegion><Start>本</Start><End>本</End></CharacterRegion> <CharacterRegion><Start>語</Start><End>語</End></CharacterRegion> </CharacterRegions> この方法を使うことによって、カスタム・プロセッサーを書かずに日本語を表示することができます。   やっぱり面倒 確かに、上記の方法でも文字数が少なければ手動で良いのですが、やはり一文字づつコードを指定するのは面倒です。 そこで、今回は入力した文字列から使用している文字を抜き出してCharacterRegions宣言部分を生成するツール、ChracterRegionジェネレーターを作ってみました。 実行ファイル: http://higeneko.net/hinikeni/tool/CharacterRegionGenerator-bin.zip ソースファイル: http://higeneko.net/hinikeni/tool/CharacterRegionGenerator-src.zip このツールはWPF 4.0を使って作られています。XNA Game Studio 4.0をインストール時に.Net…

1

動的頂点バッファのNoOverwriteとDiscard

今まで何度か動的頂点バッファについて触れてきましたが、実際のコードがどうなるのかは記事の中では紹介していませんでした。実は今までに紹介してきたサンプルの中でWritableVertexBuffer<T>というクラスがすでに実装されているので、このクラスを紹介します。 「GPUはいつ描画するのか?」の記事の中でSetDataOptions.NoOverwriteの説明をしました。この記事の中でNoOverwriteというのはプログラムがドライバへ伝えるヒントで、GPUが頂点バッファをアクセスしている領域にはSetDataで上書きすることはありませんよということを述べました。 では、実際にプログラムの中でこの処理をどうやったら良いでしょう?真っ先に思いつくのは以下のようなコードでしょう。 // 動的頂点バッファの生成 DynamicVertexBuffer vb = new DynamicVertexBuffer( graphicsDevice, typeof(MyVertexType), 100, BufferUsage.WriteOnly); // 書き込み先 int currentPosition = 0; int strideSize = vb.VertexDeclaration.VertexStride; // バッファの最後まで来たら、バッファの先頭へ戻る if (currentPosition + myVertices.Length > vb.VertexCount) currentPosition = 0; // 現在の書き込み先へNoOverWriteオプションを使って書き込む vb.SetData(currentPosition * strideSize, myVertices, 0, myVertices.Length, strideSize, SetDataOptions.NoOverwrite); // 書き込み先を更新する currentPosition += myVertices.Length; 考え方としては あらかじめ大きめの頂点バッファを生成する 現在の書き込み先(要素単位)を表すcurrentPosition変数を用意する データの書き込み時にはcurrentPositionから書き込み先のオフセット(バイト単位)を計算して、NoOverwriteオプションを指定して書き込む currentPositionを書き込んだ要素分だけ進める…

0

Dream Build Play 2011開催

今年もDream Build Play 2011が開催されます。 http://www.dreambuildplay.com/ 賞金総額75,000ドル、優勝者には賞金の他にXbox LIVEアーケードタイトルとして発売する権利も与えられます。 大会への登録期限は5月17日までで、すでに受付は開始されています。そして、作品の受け付けは5月17日~6月14日までとなっています。この日付はいずれも米国中部標準時(GMT-06:00)なので日本時間(GMT+08:00)との時差があることに注意してください。その後、応募された作品の中からトップ20までの作品が8月までに発表され、8月末に受賞者が発表される予定です。 毎年、世界中からの参加者があり、去年の受賞者には日本人の作品が2位になったので、今年も日本から受賞者がでることを期待しています。 登録する作品はXNA Game Studio 4.0で作られたXbox 360用のゲームである必要があります。 作品登録は6月14日までとなっていますが、その前の5月17日までの参加登録をするのを忘れないようにしてください。 まずは、このページの「Register Now」を押して登録しましょう。

0

XNA 3.1から4.0への更新

英文ですが、XNA 3.0からXNA 4.0への更新についてのまとまった情報があるので紹介します。 http://www.nelxon.com/blog/xna-3-1-to-xna-4-0-cheatsheet/

0