5-3 テクスチャ

ここではDirect3Dが扱える画像ファイルと、テクスチャについて説明します。

■RGBカラーとアルファ

さすがに知らない人はいないと思いますが、いま目の前のモニタが表示している色というのは、
Red(赤)、Green(緑)、Blue(青)の3色を合成することで表現しています。
これを光の3原色と言いますが、例えばこの3色を全て最大値で合成した場合は白に見え、
反対に全て最小値(無し)だった場合は黒になります。

知らない人はモニタを虫眼鏡で見てみよう!
高解像度のEGZOなら顕微鏡でwww


次にアルファというのは簡単に言うと透明度で、これは上の光とは関係なく単にその色を描画するときに、
背景と合成する時の量を指定するものです。

以下はこのRGBとアルファをスライダーで動かすことで、実際にどのような色となるかを見れるサンプルです。


RGBとアルファはそれぞれ8bitの分解能、つまり256段階で表現することが出来ますが、
PCモニタでフルカラーと言うのはこのRGBをフルに使ったもので別名24bitカラーとも言います。
※24bitは1677万色ですが、最近では各色10bitで合計30bitの10億7374万色に対応したディープカラーというのが存在します

また画像ファイルにはRGBだけ保存した24bitカラーの他、
RGBとアルファをセットにした32bitカラー対応のフォーマットがあります。


ちなみに最近のグラフィックボードには32bitフルカラーといった表現がありますが、
実はこれはアルファ分の8bitが使われておらず実質24bitカラーと同じ意味となります。

理由はグラフィックボードの問題で、処理的には24bit(3byte)ごとに演算するより
キリの良い32bit(4byte)で演算した方が効率が良いからです。

この時のアルファ8bit分は何も使用しないということでXと表現し、
Direct3DではXRGBといった表現で表記されることがあります。
※画像として使用する場合はXは0x00ではなく0xFFとなり、完全な不透明扱いとなります

■アルファチャンネル付き画像ファイル

画像ファイルと言えば一般的にはBMPファイルを思いつくと思いますが、
前の説明にあるアルファチャンネルを含める場合は基本的にTGA(ターガ)ファイルを使用します。

なおアルファ合成を行わない画像は通常はBMPを使いますが、実は最近ではBMPでもアルファ付きファイルが扱えるため、
作成ソフトが対応しているのであればTGAではなくBMPを使うことも可能です。

ここではアルファチャンネル付き画像というのがどういう形式なのかについて詳しく説明しますが、
実はBMPとTGAはヘッダ部分が異なるだけで中身はほぼ同じなので、この内容はどちらにも当てはまります。


ではまずアルファチャンネルについて説明します。

アルファチャンネルは作成ソフト上で見た場合、黒~白のモノクロ画像に見えますが、
実際はそのピクセルの色が0~100%の透明度を表しています。
※ソフト上ではあくまでもデータを可視化するためにモノクロ表示にしているだけです

まず以下の画像を見てください。(300%に拡大しています
)

RGBチャンネル アルファチャンネル

これらの画像ですが、仮にRGBチャンネルの特定の1ピクセルと同じ座標にあるアルファチャンネルの色を見ると、
まったく半透明を行わない箇所は真っ白(Alpha=255/100%表示)ですが、完全に透明になる箇所は真っ黒(Alpha=0/0%表示)となっています。

そしてここが重要なところですが、キャラクターの主線のふち部分をよく見ると灰色(Alpha=1~254)となっています。
つまり1%~99%の透明度で合成すると言うことですが、1ドットごとにこの透明度が背景色と計算されることで、
最終的にきれいなふちとなるわけです。

※スライドバーでズームするので、画像をドラッグしてふちを見てみよう

そして上記の2つの画像を1つに保存したものが32bitのTGAファイルとなり、DirectXではBMPとこのTGAを標準でサポートしています。

なお、よく勘違いをされることとして黒を表示したい場合はRGB値は黒ですが、アルファも黒としてしまう人が多いことです。
よく考えれば分かると思いますが黒にアルファの黒、つまり完全な透明を合成するということは結果は何も描画されないということになります。
黒を描画するにはアルファは100%、つまり白にしなければなりません。

これは上のRGBスライダーサンプルにて確認することが出来ます。
テストをする場合はRGBを全て0にした状態でアルファを変更してみてください。


ちなみに昔のゲームのように、あえてドット絵のようにジャギを目立たせたい場合は、
以下のようにハッキリと白黒にすればOKです。





TGAが扱えるソフトとしてはPhotoshopやPaintShopがありますが、Windows標準のペイントアプリでは作れません。
何かしらのソフトウェア(フリーソフトなど)でTGAの扱えるソフトを探しましょう。

なおTGAには圧縮版と未圧縮版がありますが、DirectXでは圧縮版は使えないと思ったので未圧縮を使用するようにしましょう。
ちなみにTGA自体は仕様が公開されているため、自前でソフトを作ることも可能ではあります。

■テクスチャ

画像の形式が分かったところで、次にDirect3Dでロード出来る画像の基本的な仕様を説明します。
Direct3Dに画像を読み込むとその画像は3Dで描画するための状態、つまりテクスチャになります。

このテクスチャには以下のような制限があります。

①基本的に幅と高さは2の累乗でなければならない
 実際にはDirect3D9からは2の累乗でなくても動作はしますが、
 グラフィックボードによっては内部で2の累乗などに変換されてしまい、
 表示すると汚くなることがあります
②ハードウェアにより最大のサイズが決まっている
 最近のグラフィックボードなら縦横それぞれ8192pxといった解像度に対応していますが、
 昔のものでは1024pxや2048pxまでしか対応していないものが存在します 

Direct3DにはD3DXライブラリと言う画像ファイルをテクスチャとしてロードするための関数が用意されていますが、
これは上記の制限を受けるため、内部で画像が勝手に変更されてしまうことがあります。

たとえば幅と高さが2の累乗ではない画像をロードしようとすると、自動的にテクスチャがスケーリングされてロードされてしまいます。
また、ハードウェアの最大値を超えた場合はその最大値になるように縮小されてしまいます。

これらの制限はこの関数で吸収されますが、実際に使う際にはこれらを考慮する必要があるため、
表示が面倒なことになる前に始めから対応したサイズで作成しておきましょう。

なお幅と高さそれぞれが2の累乗と言っていますが、これは必ず正方形であるという意味ではありません。

昔のハードウェア(3dfxのVoodooシリーズなど)には必ず正方形でなければならないというものがありましたが、
現在はそのようなハードウェアは存在しないので、基本的に正方形ではないテクスチャでも問題ありません。

また、テクスチャの最大サイズも現状のハードなら2048x2048は最低でも対応しているため、
フルHDレベルの画像ならば特に問題なく使用出来ます。

もし古いハードウェアにも対応させたい場合、Direct3Dの関数でそのハードのスペックを調べることが出来るので、
これを利用して低解像度の画像に切り替えるといったことを行います。
IDirect3D9::GetDeviceCaps()D3DCAPS9MaxTextureWidthMaxTextureHeightなど


テクスチャの容量についてですが、たとえば640x480のゲーム画面の背景に1枚テクスチャを用意するとします。

この場合テクスチャのサイズは2の累乗にしなければならないので、実際には1024x512の画像が必要となります。
これをそれぞれアルファ有りと無しで作成した場合、だいたい以下の容量のメモリを使うことになります。

アルファ無し アルファ有り
約1.5M 約2.0M

最近のグラフィックボードはVRAM(グラフィックボード上のメモリ)が512Mや1024Mとかなり多いですが、
昔のグラフィックボードは8Mや16M、32Mなどとても少ない容量しかありません。
このため最初にある程度ゲームのスペックを考えてから、必要な画像枚数など仕様として決めておく必要があります。

例えばメモリが足りない場合は最初に全ての画像をロードしておくのではなく、
シーンごと(タイトルやメインゲーム画面など)に以前の画像をアンロードしてから
新たにロードするといったやり方を考慮しておく必要があります。
※アーケードゲームなどでは最初に全てロードしておくことで画面遷移などでロード待ちが発生しないようにしています。
 これは人をたくさん回すためにはロード時間も惜しいからという意味もあります。

ちなみにいくらVRAMが8Mあるからといってもアルファ有りの画像(1024x512)が4枚入るというのは危険です。
これはDirect3Dでは描画を行うために頂点変換やライティングといった他の処理にもVRAMを使用しているためで、
実際にはもっと少ない容量となるためです。

※よくあるのが、スペックのことをまったく知らない企画の人間がゲームの演出にこだわり過ぎて、
 この仕様では無理だと言うと何故かプログラマーの技量が足りないせいにされたり、
 物理的に無理なのにプログラマーが嫌がって作ってくれないなどと意味不明なことを言う人もいるので、
 そのような状況に陥らないためにもプログラマーはある程度の知識や仕様を考える能力を持っておくべきです
 (やりたいこととやれることは別問題なので、そのあたりを理解してくれる企画者は知識のある良い企画者です)



■UV座標

次にこのテクスチャ画像上での位置を識別するためのUV座標という概念について説明をします。
簡単に言うとUV座標とは、テクスチャの幅と高さを常に0.0~1.0の少数値で表現した値となります。

たとえば以下の画像を見てください。

テクスチャのサイズ関係なしに常に0.0~1.0までの値がテクスチャに付き、
その中のあるピクセルの座標を表現するためには、そのピクセルの座標から画像サイズを割って求めます。

具体的に式で表すと以下のようになります。
 U = 指定のX座標 / テクスチャの幅
 V = 指定のY座標 / テクスチャの高さ

難しそうに見えますが、ようはそのテクスチャの幅と高さを100%とし、
その座標が何%なのかを算出するようなイメージです。

このように3Dで画像を扱うときは多少面倒な規約が存在しますが、
実はUV座標には利点があって、これはどのような画像のサイズでも常に0~1となるので、
例えばあとで高解像度(もっと大きい)の画像に変更しても、
0~1の座標は変わらないのでプログラムの修正を行わずに差し替えが出来ます。

通常の3Dゲームでは処理速度を稼ぐために、あまり目立たないようなテクスチャは小さなものを、
地面や壁など目立つところは大きなテクスチャを使ったりしますが、
もしPCの性能が高ければ、目立たないところでも大きなテクスチャを使って
より完成度の高い画面を作り出すことが出来ますが、逆に性能が低いPCならば
全てのテクスチャを低解像度にすることで処理を軽くすることが出来たりします。

この時UVを作りなおすという手間が要らないため、単に画像を差し替えるだけで済みます。


とりあえずここまでである程度Direct3Dの仕様が見えてきたと思いますので、
次からは実際にDirect3D9を使って描画処理をしてみましょう。