> 質問内容とは関係ないのですが、ならばCPUではなくGPUでパソコン作ればいいのでは?と思いました^^;
GPUは内部で沢山の小型プロセッサを持つことで総計算力でCPUの数倍・数十倍という性能を出しているのですが
小型プロセッサ一つ一つはCPUほど機能が沢山無く一つ辺りの性能も低いので、もしGPUにCPUの代わりをさせると
シングルスレッドのソフトが軒並みCPUの場合より動作が遅くなるということになると思います
ただ「ならば性能の高く面積を喰うプロセッサ一つと性能が低く面積の喰わないプロセッサを沢山積めば良いじゃないか」
という考えはあって、PS3で使用されているCELLなんかは正にその流れのCPUです
実際に小型プロセッサを使い切った時のCELLの処理能力は同時期に販売されていたPC用CPUの数倍の性能があったと思います
現在では「高性能で面積喰うプロセッサのCPUと性能が低く面積の喰わないプロセッサを沢山持ったGPUを合体させればいいんじゃないか?」
という流れになっているようです
> >MV1SetPosition で座標を設定する、というお話でしょうか?
> はい、そうです。
移動したい座標を MV1SetPosition の第二引数に渡せばモデルを移動できます
という回答で良いのでしょうか?
> ということは、DrawPolygonIndexed3Dの頂点データをVRAMにおけば、早くなるはずですよね?
> VRAMに置く事は出来るのでしょうか?
はい、CreateVertexBuffer と CreateIndexBuffer を使用すれば可能です
機能を実装した当時の書き込みを転載しましたのでよろしければご覧ください
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
追加した関数は以下の関数です
// 頂点バッファ用の関数
// 頂点バッファを作成する( 戻り値 -1:エラー 0以上:頂点バッファハンドル )
int CreateVertexBuffer( int VertexNum, int VertexType /* DX_VERTEX_TYPE_NORMAL_3D 等 */ ) ;
// 頂点バッファを削除する
int DeleteVertexBuffer( int VertexBufHandle ) ;
// 頂点バッファに頂点データを転送する
int SetVertexBufferData( int SetIndex, void *VertexData, int VertexNum, int VertexBufHandle ) ;
// インデックスバッファ用の関数
// インデックスバッファを作成する( 戻り値 -1:エラー 0以上:インデックスバッファハンドル )
int CreateIndexBuffer( int IndexNum, int IndexType /* DX_INDEX_TYPE_16BIT 等 */ ) ;
// インデックスバッファを削除する
int DeleteIndexBuffer( int IndexBufHandle ) ;
// インデックスバッファにインデックスデータを転送する
int SetIndexBufferData( int SetIndex, void *IndexData, int IndexNum, int IndexBufHandle ) ;
// 頂点バッファ・インデックスバッファを使用してポリゴンを描画するための関数
// 頂点バッファを使用して3Dポリゴンを描画する
int DrawPolygon3D_UseVertexBuffer( int VertexBufHandle, int GrHandle, int TransFlag ) ;
// 頂点バッファとインデックスバッファを使用して3Dポリゴンを描画する
int DrawPolygonIndexed3D_UseVertexBuffer( int VertexBufHandle, int IndexBufHandle, int GrHandle, int TransFlag ) ;
DrawPolygonIndexed3D のサンプルプログラムを上記の関数を使用するようにすると以下のようになります
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
VERTEX3D Vertex[ 4 ] ;
WORD Index[ 6 ] ;
int VertexBufHandle ;
int IndexBufHandle ;
// DXライブラリの初期化
ChangeWindowMode( TRUE ) ;
if( DxLib_Init() < 0 )
{
// エラーが発生したら直ちに終了
return -1 ;
}
// 4頂点分の頂点バッファを作成
VertexBufHandle = CreateVertexBuffer( 4, DX_VERTEX_TYPE_NORMAL_3D ) ;
// 6個分のインデックスバッファを作成
IndexBufHandle = CreateIndexBuffer( 6, DX_INDEX_TYPE_16BIT ) ;
// 4頂点分のデータをセット
Vertex[ 0 ].pos = VGet( 100.0f, 100.0f, 0.0f ) ;
Vertex[ 0 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 0 ].dif = GetColorU8( 255,255,255,255 ) ;
Vertex[ 0 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 0 ].u = 0.0f ;
Vertex[ 0 ].v = 0.0f ;
Vertex[ 0 ].su = 0.0f ;
Vertex[ 0 ].sv = 0.0f ;
Vertex[ 1 ].pos = VGet( 250.0f, 100.0f, 0.0f ) ;
Vertex[ 1 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 1 ].dif = GetColorU8( 255, 0,255,255 ) ;
Vertex[ 1 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 1 ].u = 0.0f ;
Vertex[ 1 ].v = 0.0f ;
Vertex[ 1 ].su = 0.0f ;
Vertex[ 1 ].sv = 0.0f ;
Vertex[ 2 ].pos = VGet( 100.0f, 300.0f, 0.0f ) ;
Vertex[ 2 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 2 ].dif = GetColorU8( 0,255,255,255 ) ;
Vertex[ 2 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 2 ].u = 0.0f ;
Vertex[ 2 ].v = 0.0f ;
Vertex[ 2 ].su = 0.0f ;
Vertex[ 2 ].sv = 0.0f ;
Vertex[ 3 ].pos = VGet( 400.0f, 200.0f, 0.0f ) ;
Vertex[ 3 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 3 ].dif = GetColorU8( 0,255,255,255 ) ;
Vertex[ 3 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 3 ].u = 0.0f ;
Vertex[ 3 ].v = 0.0f ;
Vertex[ 3 ].su = 0.0f ;
Vertex[ 3 ].sv = 0.0f ;
// 2ポリゴン分のインデックスデータをセット
Index[ 0 ] = 0 ;
Index[ 1 ] = 1 ;
Index[ 2 ] = 2 ;
Index[ 3 ] = 3 ;
Index[ 4 ] = 2 ;
Index[ 5 ] = 1 ;
// 頂点データを頂点バッファに転送
SetVertexBufferData( 0, Vertex, 4, VertexBufHandle ) ;
// インデックスデータをインデックスバッファに転送
SetIndexBufferData( 0, Index, 6, IndexBufHandle ) ;
// 頂点バッファとインデックスバッファを使用した2ポリゴンの描画
DrawPolygonIndexed3D_UseVertexBuffer( VertexBufHandle, IndexBufHandle, DX_NONE_GRAPH, FALSE ) ;
// キー入力待ちをする
WaitKey() ;
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
頂点バッファとインデックスバッファを CreateVertexBuffer と CreateIndexBuffer で作成して、
そこにそれぞれ SetVertexBufferData と SetIndexBufferData でデータを転送して、
描画は DrawPolygonIndexed3D の代わりに DrawPolygonIndexed3D_UseVertexBuffer を使用する、
という感じです
頂点データを VRAM に置いておく、というのが速度面での一番の強みですので、なるべく
SetVertexBufferData や SetIndexBufferData は一回だけ呼ぶようにして、
描画する直前に毎回 SetVertexBufferData、SetIndexBufferData でデータを VRAM に
転送するというのは避けてください( 毎回転送してもエラーにはなりませんが、遅いです )
ただ、この機能は VRAM に転送された頂点データの計算処理に GPU が対応していない場合は DrawPolygonIndexed3D と同じ速度で動作します
こちらに頂点バッファを使用して描画した場合と、頂点バッファを使用せずに描画した場合の速度差を計測するサンプルプログラムを載せておきますので、
よろしければお試しになってみてください m(_ _)m ( 実行すると頂点バッファを使用した場合と使用しなかった場合の描画に掛かった時間が表示されます )
GPU が頂点データの計算処理に対応している場合は頂点バッファを使用した方が数倍高速に処理されますが、
表示される処理時間が殆ど同じ場合は、GPU が頂点データの計算処理に対応していないということになります
( 読み込んでいるモデルファイル DxChara.x はDXライブラリの「サンプルプログラム実行用フォルダ」の中にあります )
#include "DxLib.h"
#include <malloc.h>
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
VERTEX3D *Vertex ;
WORD *Index ;
int VertexBufHandle ;
int IndexBufHandle ;
int ModelHandle ;
int IndexNum ;
int VertexNum ;
int i ;
LONGLONG Time1, Time2 ;
MV1_REF_POLYGONLIST RefMesh ;
// DXライブラリの初期化
ChangeWindowMode( TRUE ) ;
if( DxLib_Init() < 0 )
{
// エラーが発生したら直ちに終了
return -1 ;
}
// 裏画面を描画対象にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// Zバッファを使用する
SetUseZBufferFlag( TRUE ) ;
// Zバッファへの書き込みを行う
SetWriteZBufferFlag( TRUE ) ;
// バックカリングを行う
SetUseBackCulling( TRUE ) ;
// モデルの読み込み
ModelHandle = MV1LoadModel( "DxChara.x" ) ;
// 画面に映る位置に3Dモデルを移動
MV1SetPosition( ModelHandle, VGet( 320.0f, 0.0f, 600.0f ) ) ;
// 参照用メッシュの作成
MV1SetupReferenceMesh( ModelHandle, -1, TRUE ) ;
// 参照用メッシュの取得
RefMesh = MV1GetReferenceMesh( ModelHandle, -1, TRUE ) ;
// 頂点の数とインデックスの数を取得
IndexNum = RefMesh.PolygonNum * 3 ;
VertexNum = RefMesh.VertexNum ;
// 頂点データとインデックスデータを格納する頂点バッファとインデックスバッファを作成
VertexBufHandle = CreateVertexBuffer( VertexNum, DX_VERTEX_TYPE_NORMAL_3D ) ;
IndexBufHandle = CreateIndexBuffer( IndexNum, DX_INDEX_TYPE_16BIT ) ;
// 頂点データとインデックスデータを格納するメモリ領域の確保
Vertex = ( VERTEX3D * )malloc( sizeof( VERTEX3D ) * VertexNum ) ;
Index = ( WORD * )malloc( sizeof( WORD ) * IndexNum ) ;
// 頂点データをコピー
for( i = 0 ; i < VertexNum ; i ++ )
{
Vertex[ i ].pos = RefMesh.Vertexs[ i ].Position ;
Vertex[ i ].norm = RefMesh.Vertexs[ i ].Normal ;
Vertex[ i ].dif = RefMesh.Vertexs[ i ].DiffuseColor ;
Vertex[ i ].spc = RefMesh.Vertexs[ i ].SpecularColor ;
Vertex[ i ].u = RefMesh.Vertexs[ i ].TexCoord[ 0 ].u ;
Vertex[ i ].v = RefMesh.Vertexs[ i ].TexCoord[ 0 ].v ;
Vertex[ i ].su = RefMesh.Vertexs[ i ].TexCoord[ 1 ].u ;
Vertex[ i ].sv = RefMesh.Vertexs[ i ].TexCoord[ 1 ].v ;
}
// インデックスデータをコピー
for( i = 0 ; i < RefMesh.PolygonNum ; i ++ )
{
Index[ i * 3 + 0 ] = ( WORD )RefMesh.Polygons[ i ].VIndex[ 0 ] ;
Index[ i * 3 + 1 ] = ( WORD )RefMesh.Polygons[ i ].VIndex[ 1 ] ;
Index[ i * 3 + 2 ] = ( WORD )RefMesh.Polygons[ i ].VIndex[ 2 ] ;
}
// 頂点バッファとインデックスバッファにデータを転送
SetVertexBufferData( 0, Vertex, VertexNum, VertexBufHandle ) ;
SetIndexBufferData( 0, Index, IndexNum, IndexBufHandle ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 画面をクリア
ClearDrawScreen() ;
// 頂点バッファ描画の時間計測
Time1 = GetNowHiPerformanceCount() ;
DrawPolygonIndexed3D_UseVertexBuffer( VertexBufHandle, IndexBufHandle, DX_NONE_GRAPH, FALSE ) ;
Time1 = GetNowHiPerformanceCount() - Time1 ;
// 画面をクリア
ClearDrawScreen() ;
// 通常描画の時間計測
Time2 = GetNowHiPerformanceCount() ;
DrawPolygonIndexed3D( Vertex, VertexNum, Index, IndexNum / 3, DX_NONE_GRAPH, FALSE ) ;
Time2 = GetNowHiPerformanceCount() - Time2 ;
// 掛かった時間を描画
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "頂点バッファ使用 :%4d micro sec", Time1 ) ;
DrawFormatString( 0, 16, GetColor( 255,255,255 ), "頂点バッファ未使用:%4d micro sec", Time2 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}