ページ 11

DirectXプログラミングでの自由変形描画について

Posted: 2010年6月28日(月) 15:39
by シエル
いつもお世話になります。

DirectxのID3DXSpriteを使って2D描画を行いゲームを作成しているのですが、
拡大や回転などはできるものの、画像を自由に変形して描画することが出来ません。
ここで言っている自由変形とは、DXライブラリで言うとDrawModiGraph関数を使った描画のようなことです。
ID3DXSpriteでは、画像を自由に変形して描画することは不可能なのでしょうか?

また、不可能であれば、他の方法を教えてください。
(このインターフェースを使って、~して描画する。等)

あと、各ドットの明るさを加算する方法をご存知の方がいらっしゃれば、教えていただけると助かります。

DirectXに限った回答をお願い致します。
他のライブラリ等を使うことは考えていません。

投げやりで申し訳ございませんが、よろしくお願い致します!

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月28日(月) 16:46
by ISLe
> また、不可能であれば、他の方法を教えてください。
> (このインターフェースを使って、~して描画する。等)

テクスチャを貼ったポリゴンを変形という方法になります。
いろいろ状況に応じた前後処理が必要なので説明が難しいです。

"DrawPrimitiveUp スプライト"
"DrawIndexedPrimitiveUp スプライト"
といったキーワードで検索してみてください。


> あと、各ドットの明るさを加算する方法をご存知の方がいらっしゃれば、教えていただけると助かります。

"SetRenderState 加算合成"
のキーワードで検索してみてください。

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月28日(月) 16:56
by ideyan
私もスプライトを使って色々試してみてますが
自由変形描画の方法は分かりませんでしたので、
そこだけは別の方法を使って実装しています。

1.▲ポリ2枚で1枚の■ポリを用意する。
2.それにテクスチャを貼って描画する。

座標変換済みの頂点を使えば2D座標で扱えるのでそこそこ便利だと思います。

△ポリ2枚なので添付画像(画面は800*600)のように微妙に歪な変形になるのがちょっと残念です。
(もっと細かくわければそれらしくなるとは思います)

とりあえず、自分のライブラリから該当部分の実装方法だけを
抜き出してきました。
見にくくて申し訳ないですが、よろしければご参考までに。

#長々と書いてる間にレスがついてしまいました^^;

#define MY_VER_FVF3 (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) //モード設定

typedef struct textureImage{
    IDirect3DTexture9 *pTex;//←今回はこれが必要
    float as_width,as_height;
    D3DXVECTOR3 Center;
    int width,height;
    int usage;
    textureImage():pTex(NULL){}
} Img;

typedef D3DXVECTOR3 VEC3;
typedef D3DXVECTOR2 VEC2;

//頂点データの構造体
typedef struct myVertexC{
    VEC3 p;
    float rhw;
    DWORD col;
    VEC2 t;
}mVC;

void drawMod2d(Img *img,VEC2 *vec){
    static mVC vb[4]={
        {VEC3(0,0,0),1.0f,D3DXCOLOR(1.0f,1.0f,1.0f,1.0f),VEC2(0.0f,0.0f)},
        {VEC3(0,0,0),1.0f,D3DXCOLOR(1.0f,1.0f,1.0f,1.0f),VEC2(1.0f,0.0f)},
        {VEC3(0,0,0),1.0f,D3DXCOLOR(1.0f,1.0f,1.0f,1.0f),VEC2(0.0f,1.0f)},
        {VEC3(0,0,0),1.0f,D3DXCOLOR(1.0f,1.0f,1.0f,1.0f),VEC2(1.0f,1.0f)},
    };
    //左上座標
    vb[0].p.x=vec[0].x;
    vb[0].p.y=vec[0].y;
    //右上
    vb[1].p.x=vec[1].x;
    vb[1].p.y=vec[1].y;
    //左下
    vb[2].p.x=vec[2].x;
    vb[2].p.y=vec[2].y;
    //右下
    vb[3].p.x=vec[3].x;
    vb[3].p.y=vec[3].y;

    pDevice->SetFVF(MY_VER_FVF3);
    pDevice->SetTexture(0,img->pTex);
    pDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
    pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
    pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,vb,sizeof(mVC));
    
}

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月28日(月) 17:20
by シエル
>>ISLeさん
回答ありがとうございます!
これだけでも十分です。グググらせていただきます!

>>ideyanさん
詳しい説明ありがとうございます!
画像まで添付していただいて…、ありがとうございます。
貼っていただいたコードも参考にさせていただきます!

後は何とか自分で対応しますが、何か効果的な方法をご存知の方が
いらっしゃれば、回答お願い致します! 画像

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月28日(月) 17:46
by ISLe
> △ポリ2枚なので添付画像(画面は800*600)のように微妙に歪な変形になるのがちょっと残念です。
> (もっと細かくわければそれらしくなるとは思います)

それは頂点数とは関係ないと思います。
詳しくは↓の記事を。

テクセルとピクセル間の直接マッピング
http://msdn.microsoft.com/ja-jp/library/cc373047.aspx

変換済み座標を使う場合スクリーン座標すべて-0.5fすれば歪まなくなるはずです。

テクスチャ座標を+(0.5f/[テクスチャサイズ])しても良いようです。

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月29日(火) 09:23
by シエル
すいません。追加で質問させて下さい。

ググって色々調べてみたところ、
自分で定義した、座標変換済み頂点の配列をDrawPrimitiveUpに渡して描画する方法と、
CreateVertexBufferで頂点バッファを作成し、メモリをロックしてバッファに頂点配列を書き込み、
DrawPrimitiveで描画する方法の二つがありました。

どちらの方法を使用して描画する方が効率が良いのでしょうか?
それぞれのメリット、デメリットがあれば、教えていただけると助かります。

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月29日(火) 17:51
by ISLe
頂点バッファはグラボのVRAM上に作成されると期待できるので、いったん大量の頂点を転送したあと部分的に更新するような用途で高速化を見込めます。

DrawPrimitiveUpは毎回頂点バッファを作成して転送を行うのでオーバーヘッドが大きいと考えられます。

ただしスプライト用途では座標が大きく変化します。
DrawPrimitiveUpは実際にVRAMに転送されるまでのあいだに最適化が働きます。
自前で頂点バッファを管理してもさほど高速になりません。
スプライト用途に限ってはプログラムコードも見易くなるDrawPrimitiveUpがお勧めです。

あと高速化のために、SetFVF、SetTexture、Set~State、等をできるだけまとめて、DrawPrimitiveUpを連投するようにしてください。
属性の切り替えはとても時間のかかる処理です。
環境にもよりますが毎回SetTextureしないようにするだけで3倍くらい速くなることもあります。

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月29日(火) 18:38
by シエル
お忙しいところ回答ありがとうございます!
座標がさほど変化しないようであれば、頂点バッファを作成して描画し、
座標が大きく変化するようであれば、DrawPrimitiveUpを使います!

属性の切り替えについても、呼び出すタイミングや回数について悩んでいるところでした。。。
アドバイスありがとうございます。できるだけまとめて回数を減らします。

で、書いてる間にちょっと気になったのですが、
一般的に、Directxで2Dのゲームを作成するときの描画方法として、

・スプライトで表現できる描画であれば、基本的にスプライトで描画。
・複雑な描画であれば、ポリゴンにテクスチャを貼って描画。

というような感じで、皆さんはゲームを作成されているのでしょうか?

何度も追加質問で申し訳ございません。よろしくお願い致します!

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月30日(水) 02:02
by ISLe
> 座標がさほど変化しないようであれば、頂点バッファを作成して描画し、
> 座標が大きく変化するようであれば、DrawPrimitiveUpを使います!

「さほど」「大きく」というのは数値の大小ではなくてデータ量の話です。
とりあえずUP系を使うようにして使い分けは考えなくて良いと思いますよ。

例えば3Dゲームの舞台となる地形のデータはおおかたずっと変化しませんよね。
そういうデータをビデオメモリに置きっぱなしにすることで転送コストを減らすわけです。


> ・スプライトで表現できる描画であれば、基本的にスプライトで描画。
> ・複雑な描画であれば、ポリゴンにテクスチャを貼って描画。

スプライトとポリゴンの違いって何でしょう?
背景で3D描画するときとかはもちろんポリゴンなんですけど。
変換済み頂点使うのとビルボードとの違いってところでしょうか。

Re:DirectXプログラミングでの自由変形描画について

Posted: 2010年6月30日(水) 09:22
by シエル
ISLeさん、返答ありがとうございます。
頑張って作成していきます!

#DirectXのヘルプすごい分かりづらいですね…