とにかく使ってみようゼェ、DirectX8講座
〜〜 基礎編・DirectX8予備知識 〜〜
★その1:今までとどう違うか
 まず初めに今までのDirectX7とDirectX8はどう違うかというところから。

ずばり、大きな変更点はというと、
  まる1:DirectDrawがDirect3Dに吸収され、DirectXGraphicになった。
  まる2:256色が使えなくなり、High Color(16bit)以上になった。
といったところであろうか。

 で、それがいままでDirectDrawを使ってた人にどう影響するかというと、ぢつは以外と大したことはなかったりする。

 まず、まる1の方から具体的に見ていって見よう。

DirectDrawでの大雑把な描画の手順は
  1:用意しておいたビットマップからサーフェイスを作る。
  2:サーフェイスの使いたい矩形を指定する。
  3:送り先を指定して転送する。
という感じであった。

 これに対し、DirectXGraphicではどうなったかというと、
  1:用意しておいたビットマップからテクスチャを作る。
  2:テクスチャの使いたい部分を指定する。
  3:描画先を指定してレンダリングする。
ってな感じで、さほど変化が見られなかったりする。

 以外に思うかもしれないが、実際にはこんなもんである。
Direct3Dとくっついたことで、3Dを扱うための関数とかは確かに増えたし、
全てポリゴンを使うことにもなったが、そんなん気にしなければどうということはない。

 んで次、まる2の方だが、これはけっこうデカいかもしれない。 まぁ、何とかならないでもないと思うが。

 256がなくなって困るのはズバリ
  ・パレット
  ・処理速度
の2点だろう。

 はっきり言って処理速度の方はどうにもならない、が、今のパソコンだと性能がいいから割と平気そうな気はする。
 だがパレットの方は、ぢつは使える、らしい、俺には使い方がよく分からなかったが。

 あと、全体的に赤くする、みたいなことなら別の方法がある、頂点色だ。
といわけで、次はその辺の説明を。


★その2:頂点
 DirectXGraphicで何かを描画する場合、普通は頂点を4つ決めて、 そこにテクスチャをレンダリングするのだが、その頂点の話だ。

 頂点は位置や色などの要素を必要に応じて選べるようになっているが、俺は
  ・位置(x,y,z)
  ・RHW
  ・ディフューズ色
  ・テクスチャ座標(tu,tv)
を使っている。

 位置はそのものズバリ頂点のある位置のことだ。
Z座標もあるが、実際のレンダリングには関わってこない、Zは別の目的に使うのだ。 (3Dなソフトはそうでもないが)

 ディフューズ色はさっきの頂点色のことで、これを赤にしておけば、 たとえテクスチャが真っ白でも赤く表示されることになるわけだ。
ちなみに、これをいじればグラデーションをかけることも簡単に出来る。

 テクスチャ座標というのは、その頂点がテクスチャのどこを表すかを示す物だ。
これがやっかいなことに、左上を(0,0)右下を(1,1)として指定しなければならない。
まぁドット単位で指定しておいてテクスチャの大きさで割ればいいだけのことなのだが。

 RHWは俺にはよく分からなかったが、とりあえず1にしておけばいいようだ。


★その3:テクスチャ
 実はテクスチャには大きさに制限があったりする。
  ・一辺の長さは2のn乗でなければならない。
  ・ある程度より大きいテクスチャは作れない。
という感じだ。

 タテヨコのサイズはけっこう微妙で、256の次が512、その次はもう1024、 よく考えて絵を描かないとテクスチャが隙間だらけになること請け合いだ。
 ちなみにこれを違反すると、強制的にこの大きさにされてしまい、せっかく描いた ドット絵が見るも無惨なことになってしまう。

 あと、テクスチャの大きさの制限はマシンによって異なるようだが、だいたい 一辺1024くらいか。

 ちなみに、某渡辺のパ(略)ブレ(略)を持っているならDebug.txtの下の方に 書かきこまれるので便利だ。
微妙に信頼性は低いが、まぁ、目安にはなるかと。


★その4:Zバッファ
 さっき、頂点のZ座標は描画には使わないといったが、では何に使うかというと、 手前にあるはずの物のより前に奥にあるはずの物を描画してしまったりしないように チェックするのに使うのだ。
んで、それに使うのがZバッファである。

 普通ならこれは、変な風に突き刺さっているポリゴンを正しく描画するのに使うが、 ぢつはもう一つ使い道があって、上手く使うと処理速度が上げられるのだ。

 どうするかというと、Zバッファを有効にしておいて、手前から描画するのだ。
すると、二回以上描画するよりもZ値ではじいた方が早いので、処理速度がアップする。

 ただし、半透明なポリゴンは奥から描画しないと、ちゃんと半透明にならないので注意。


★その5:ミップマップ
 基本的に、テクスチャを拡縮して描画しようとすると処理速度が低下するのだが、 どうやら、その率が大きければ大きいほど処理速度も大きく低下するらしい。
 んで、これをなんとかするために出来たのがミップマップだ。

 ミップマップというのは大きさが元のテクスチャの1/2、1/4、1/8...のテクスチャで、 最高で(最小で)1×1のサイズまで作れる。

 で、これを使って描画すると、いかに小さく描画しようとしてもテクスチャの縮小率は 絶対に1〜1/2の間に収まるので、それほど処理速度が落ちないわけである。

 ただ、この方法は縮小して表示する場合では最も高速だが、かわりに最もメモリを喰う。
 よく考えて使おう、というほどでもないか。


〜〜 実践編・実際のコード(VB) 〜〜
★その1:まずは変数宣言
 Public DX8 As New DirectX8
 Public D3D As Direct3D8
 Public D3DPP As D3DPRESENT_PARAMETERS
 Public DDX As D3DX8
 Public DDD As Direct3DDevice8
 Public Type tVtx
   x As Single
   y As Single
   z As Single
   rhw As Single
   Color As Long
   tu As Single
   tv As Single
 End Type
 Const D3DFVF_tVtx = (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE Or D3DFVF_TEX1)
 Public cVSIB As Long

 とりあえずこれだけ宣言しておこう、それぞれの説明は追々していくということで。
ちなみに、全部グローバルなのは俺の趣味である。
あと、コード自体は自作のライブラリからコピペしてきた物なのでそのまま使えるハズ。


★その2:DirectX8の初期化(ここ全体をひとつの関数にしておくとグー)
・まる1:エラーが多分でるから...
 On Local Error Resume Next

 途中でエラーがでる可能性がある(問題なし)ので、エラーがでても次に行くようにする。

・まる2:Direct3Dオブジェクト&Direct3DXオブジェクトを作る
 Set D3D = DX8.Direct3DCreate()
 Set DDX = New D3DX8

 まず深く考えずにDirect3DオブジェクトとDirect3DXオブジェクトを初期化する。

・まる3:初期化方法を決める
 With D3DPP
   .Windowed = False
   .BackBufferCount = 1
   .BackBufferFormat = D3DFMT_R5G6B5
   .BackBufferWidth = 320
   .BackBufferHeight = 240
   .SwapEffect = D3DSWAPEFFECT_FLIP
   .AutoDepthStencilFormat = D3DFMT_D16
   .EnableAutoDepthStencil = True
 End With

 Direct3Dデバイスの初期化の仕方を決める。
 項目は上から順に、
  ・ウインドウモードかフルスクリーンモードか(Trueだとウインドウ、Falseだとフルスクリーン)
  ・バックバッファの数
    基本的に1枚でいいと思う。
    ただ、2枚以上にすると描き込みつつ別の処理が行えるから速いという話もあるが、確実に反応は1フレーム遅れることになる。
    個人的には1枚のがいい気がする。
  ・バックバッファの色数
    ここでソフトの色数が決定する。
    ちなみに、X1R5G5B5、R5G6B5、X8R8G8B8、A8R8G8B8のどれかでないとダメ。
  ・バックバッファの縦幅
  ・バックバッファの横幅
  ・バッファ スワップ動作
    要するに、バックバッファを実際に表示する方法。
    フリップの他にコピーとかがある。
  ・自動で作られるZバッファの色数
    D16というのは深度(Z値)が16bitということ。
    ぢつは深度以外にも色々あるのだが、俺にはよく分からなかったので割愛。
    ちなみにZバッファはDirect3Dデバイスと一緒に作られる。
  ・Zバッファを使うかどうか
    TrueだとZバッファを使うことになる。
    とりあえず、つかっとくに越したことはないと思う。


・まる4:Direct3Dデバイスを作る
 Set DDD = D3D.CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DPP)
 If DDD Is Nothing Then
   Set DDD = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DPP)
   If DDD Is Nothing Then
     Set DDD = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DPP)
   End If
 End If

CreateDevice関数の引数は前から順に、
  ・ディスプレイアダプタ
    よく分からんが、とりあえずデフォにしとけばいい。
  ・デバイスのタイプ
    3Dのハードウエアアクセラレーションを使う/使わないを決める。
    使わない場合はソフトウェア的にエミュレートすることになるため遅くなる。
    ただ、ハードの問題なので無いならしょうがないのだが。
  ・ウィンドウのハンドル
    なんていうか、デバイスの初期化先(?)。フォームのhWndを渡す。
  ・デバイスの全体的な動作
    ハードウェアで頂点変換処理をするか、ソフトでするか、両方でするかを決める。
    これもハードの問題になってくる。
  ・デバイスの初期化の仕方
    まる3のD3DPPを渡す。
    ちなみに、3回やってるのはハードの問題に対応するため。

・まる5:初期設定あれこれ
 Dim V As tVtx
 cVSIB = Len(V)

 まず、宣言しておいた頂点(tVtx型)の大きさ(ビット数)を取得する。
ちなみに、tVtxはtype Vertexの略で、cVSIBはconst Vertex Sizeなんとかの略、 IBがなんだったか思い出せない。

 With DDD
   .SetVertexShader D3DFVF_tVtx
   .SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
   .SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR
   .SetRenderState D3DRS_ZENABLE, D3DZB_TRUE
   .SetRenderState D3DRS_LIGHTING, False
   .SetRenderState D3DRS_ALPHABLENDENABLE, True
   .SetRenderState D3DRS_ALPHATESTENABLE, True
   .SetRenderState D3DRS_ALPHAREF, &H8&
   .SetRenderState D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL
 End With

 Direct3Dデバイスの初期設定をする
 設定するのは主にテクスチャステージステートと、レンダーステートで、 それぞれ、テクスチャの重ね方と、レンダリングの仕方を決める。
 項目は上から順に、
  ・頂点のフォーマット
  ・テクスチャを縮小して描画するときのフィルター
  ・  〃   拡大      〃
  ・Z値を使うか
  ・ライトを使うか
  ・アルファブレンドをするか
  ・アルファテストをするか
  ・   〃   に使う定数
  ・     〃    関数
 アルファテストというのはアルファ値によって描画するかどうかを決めるもので、 これをオンにしておかないとカラーキーも使えないらしい。


★その3:実際に描画する
・まる1:テクスチャを作る

 dim Tex As Direct3DTexture8
 set Tex=DDX.CreateTextureFromFileEx(DDD, "T.bmp", 0, 0, 1, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, &HFF000000, ByVal 0, ByVal 0)

 テクスチャを作るにはCreateTextureFromFileExを使う(他にもあるが)。
引数は前から順に、
  ・Direct3Dデバイス
  ・ファイル名
  ・幅(0だと元になるファイルから取得される)
  ・高さ(      〃         )
  ・ミップマップレベル
    ミップマップの数。
    0だと完全なミップマップチェーンが作成される。
  ・レンダリング先として使うかどうか
  ・フォーマット(色数)
  ・テクスチャをどこのメモリに置くか
  ・レンダリング時に使うフィルタ
  ・レンダリング時に使うフィルタ(ミップマップの)
  ・カラーキー
  ・イメージファイル内のデータの記述
    よく分からないのでByVal 0にする。
  ・格納する 256 PALETTEENTRY 型の配列の最初の要素
    パレットっぽいのだが不明、やはりByVal 0にする。

・まる2:バックバッファをクリアする(Zバッファ含む)
 DDD.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0

 説明を呼んでもイマイチよく分からなかったので、とりあえずこうする。
大丈夫、問題ない。

・まる3:Direct3Dデバイスを描画できる状態にする
 DDD.BeginScene

・まる4:レンダリングする
 Dim Vtx(3) as tVtx
  (Vtxに必要な値を設定する)
 DDD.DrawPrimitiveUP D3DPT_TRIANGLEFAN, 2, Vtx(0), cVSIB

 レンダリングにはDrawPrimitiveUP関数を使う(やはり他にもある)
引数は前から順に、
  ・頂点をどう扱うか
点として、とか、線分として、とか、3角形として、とかがある。
この種類をプリミティブという(らしい)
  ・レンダリングするプリミティブの数
  ・   〃    頂点の最初の一個
  ・     〃     サイズ(何ビットか)
 ちなみに、上のコードだと、頂点の配列を三角形(いわゆるポリゴン)2ヶとしてレンダリングする。
つまり四角形がレンダリングされるわけだ。

・まる5:Direct3Dデバイスを描画できる状態から解除する。
 DDD.EndScene

・まる6:バックバッファを実際に表示する
 DDD.Present ByVal 0, ByVal 0, 0, ByVal 0

 やはりよく分からなかったが、とりあえずこうしておけば大丈夫。
これで画面にテクスチャが表示されるはずだ。


★その4:DirectX8を終了する
 If DX8 Is Nothing Then Exit Sub  Set DXS = Nothing
 Set D3DVB = Nothing
 Set DDD = Nothing
 Set DX8 = Nothing

 ぢつは終了するには特に難しいことはなく、上のように宣言したオブジェクトを全て Nothingにすればいいだけである。
 あと、作ったテクスチャも全てNothingにすること。
さぁ、後はヤる気さえあれば何でも出来るはず!

2001/9/29、いや30 のじゃ