08
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

DirectX9でのDrawPrimitiveの回数を減らす

DirectX9でのDrawPrimitiveの回数を減らす工夫は必須なのですが

資料があんまり無い~と言う事で
ちらっと書いてみます

矩形描画でテストしただけですが…

まず仮定として『呼ばれる順に上へ塗り重ねていく』と言う前提を起きます。

そしてこんな感じで頂点のリストを持っておきます。


template
class DrawVertex
{

T* list;
public:
int Capacity;
int Count;
DrawVertex():Count(0) { list = new T[Capacity = 1420]; }
void AddVertex(T* vertexs,int length)
{
if(Count + length > Capacity )
{

T* l = new T[Capacity += Capacity / 10];//10%増やしてみる
CopyMemory(l,list,Count*sizeof(T));
delete[]list;
list = l;
}
CopyMemory(&list[Count],vertexs,length*sizeof(T));
Count += length;
}

void CopyVertex(T* dest)
{
if(Count == 0)return;
CopyMemory(dest,list,Count*sizeof(T));
}

void Clear() { Count = 0; }

~DrawVertex() { delete [] list; }
};

1420 ってのは6の倍数~ っておもったけど今考えたら違ってた… っていう数字なので適当で大丈夫です
vectorはデータが連続して入ってる事が保証されてないようなので使えないです。
(メモリコピーで済ませたいためです)

描画関数が呼ばれたときはvoid AddVertexを代わりによんでこのリストに登録します。

こんな感じです。(rectVertexが上のインスタンスです)

void DrawDevice::DrawRectangle(int x, int y, int w, int h, DWORD color)
{
int rx=x+w,ry=y+h;
XYZVERTEX v[6];



setZ += float::Epsilon * 2;
v[0].x= x; v[0].y=y,v[0].z =setZ,v[0].rhw = 1.0f,v[0].color=color;
v[1].x= rx; v[1].y=y,v[1].z =setZ,v[1].rhw = 1.0f,v[1].color=color;
v[2].x= rx; v[2].y=ry,v[2].z =setZ,v[2].rhw = 1.0f,v[2].color=color;
v[3].x= x; v[3].y=ry,v[3].z =setZ,v[3].rhw = 1.0f,v[3].color=color;
v[4] = v[0];
v[5] = v[2];
rectVertexs->AddVertex(v,6);

}
setZは後の方が上に来るという前提の元機械イプシロンの二倍ぐらいかけてあげればいいかな~ってことでしてます。

これを描画するタイミング(レンダーターゲットが変わる直前や描画が終わるタイミング)で一気に描画してあげます。
っていっても頂点のコピーはCopyVertexで一発なので難しくなく

LPDIRECT3DVERTEXBUFFER9 buffer = NULL;
if( FAILED (device->CreateVertexBuffer(rectVertexs->Count * sizeof(XYZVERTEX),
0,
D3DFVF_XYZVERTEX,
D3DPOOL_DEFAULT,
&buffer,0 ) ) )
{
throw gcnew NineTailException("描画に失敗しました。");
}

XYZVERTEX* v=0;
buffer->Lock(0,0,(void**)&v,0);
rectVertexs->CopyVertex(v);
buffer->Unlock();


device->SetStreamSource( 0, buffer,0, sizeof(XYZVERTEX) );
device->SetFVF( D3DFVF_XYZVERTEX );
device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, rectVertexs->Count / 3 );

rectVertexs->Clear();
buffer->Release();

こんな感じで描画してあげればいいわけです。
その後頂点のリストをクリアするわけですが実際は参照の位置を0に戻すだけっていうかんじです
DrawPrimitiveはトライアングルリストで(サンプルだとこれ使わない事多いよね~とか思ってみたりして…)


これをしないで正直に矩形一個一個毎回DrawPrimitiveを呼んでいると200程度で処理落ち(FPS60)を確認しました
逆にこの状態だと矩形15000個位なら平気でした まぁ、他に処理殆ど挟んでないからなので実際は矩形10000個くらいですかね~ あとは画像の枚数は20~30枚が限度ってところでしょうか… うむむ… 

DXライブラリだとどうやってるんだろ~ う~ん

一応解決策あるにはあるんですけど…
→テクスチャを一枚のテクスチャとして統合して管理してテクスチャのインスタンスには開始頂点のみ記述する
っていうのが… ね…
スポンサーサイト

Comment

Secret

検索フォーム

RSSリンクの表示

リンク

リンクというか個人的によく使うアルゴリズムの解説サイト… C#でなかったりする

ブロとも申請フォーム

この人とブロともになる

QRコード

QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。