とりあえず高速に円錐を100万個描画するプログラムを組んでみましたので
よろしければ実行して、画面左上に表示される FPS がどのくらいの値になるかを
確認してみてください( 30 に達していないとゲームとしては厳しいと思います )
#include "DxLib.h"
#include <malloc.h>
#define ONE_SPACE (15.0f)
#define ONE_VERTEXNUM (21)
#define ONE_INDEXNUM (36)
#define ONESET_X_NUM (10)
#define ONESET_Y_NUM (10)
#define ONESET_Z_NUM (10)
#define ONESET_TOTAL_NUM ( ONESET_X_NUM * ONESET_Y_NUM * ONESET_Z_NUM )
#define ONESET_TOTAL_VERTEXNUM ( ONESET_TOTAL_NUM * ONE_VERTEXNUM )
#define ONESET_TOTAL_INDEXNUM ( ONESET_TOTAL_NUM * ONE_INDEXNUM )
#define SET_X_NUM (10)
#define SET_Y_NUM (10)
#define SET_Z_NUM (10)
#define SET_SPACE (150.0f)
// 円錐の頂点データ
VERTEX3D ConeVertex[ ONE_VERTEXNUM ] =
{
{ { 0.000000f , 0.000000f, 5.000000f }, { 0.000000f, 0.447214f, 0.894427f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -3.909158f, 0.000000f, 3.117449f }, { -0.699291f, 0.447214f, 0.557666f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -4.874640f, 0.000000f, -1.112605f }, { -0.872002f, 0.447214f, -0.199029f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -2.169418f, 0.000000f, -4.504845f }, { -0.388077f, 0.447214f, -0.805851f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 2.169419f, 0.000000f, -4.504844f }, { 0.388077f, 0.447214f, -0.805851f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 4.874640f, 0.000000f, -1.112605f }, { 0.872002f, 0.447214f, -0.199029f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 3.909157f, 0.000000f, 3.117450f }, { 0.699291f, 0.447214f, 0.557666f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { 0.000000f, 0.447214f, 0.894427f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { -0.699291f, 0.447214f, 0.557666f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { -0.872002f, 0.447214f, -0.199029f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { -0.388077f, 0.447214f, -0.805851f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { 0.388077f, 0.447214f, -0.805851f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { 0.872002f, 0.447214f, -0.199029f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 10.000000f, 0.000000f }, { 0.699291f, 0.447214f, 0.557666f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 0.000000f, 0.000000f, 5.000000f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -3.909158f, 0.000000f, 3.117449f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -4.874640f, 0.000000f, -1.112605f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { -2.169418f, 0.000000f, -4.504845f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 2.169419f, 0.000000f, -4.504844f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 4.874640f, 0.000000f, -1.112605f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
{ { 3.909157f, 0.000000f, 3.117450f }, { 0.000000f, -1.000000f, 0.000000f }, { 255, 255, 0, 0 }, { 255, 255, 255, 0 }, 0.000000f, 0.000000f, 0.000000f, 0.000000f },
} ;
// 円錐の頂点インデックス
WORD ConeIndex[ ONE_INDEXNUM ] =
{
0, 7, 1, 1, 8, 2, 2, 9, 3, 3, 10, 4, 4, 11, 5, 5,
12, 6, 6, 13, 0, 14, 15, 20, 20, 15, 16, 20, 16, 19, 19, 16,
17, 19, 17, 18,
} ;
// 頂点バッファハンドル
int VertexBufferHandle ;
// 頂点インデックスハンドル
int IndexBufferHandle ;
// 頂点バッファのセットアップ
void SetupVertexBuffer( void )
{
int i ;
int j ;
int k ;
int l ;
VERTEX3D *Vertex ;
VERTEX3D *vert ;
WORD *Index ;
WORD *ind ;
float TotalXDistance ;
float TotalYDistance ;
float TotalZDistance ;
VECTOR AddPos ;
WORD AddIndex ;
// 1セットの描画範囲を計算
TotalXDistance = ONESET_X_NUM * ( ONE_SPACE - 1 ) ;
TotalYDistance = ONESET_Y_NUM * ( ONE_SPACE - 1 ) ;
TotalZDistance = ONESET_Z_NUM * ( ONE_SPACE - 1 ) ;
// 1セット分の頂点データと頂点インデックスを格納するためのメモリを確保
Vertex = ( VERTEX3D * )malloc( sizeof( VERTEX3D ) * ONESET_TOTAL_VERTEXNUM ) ;
Index = ( WORD * )malloc( sizeof( WORD ) * ONESET_TOTAL_INDEXNUM ) ;
// 1セット分の円錐の頂点データと頂点インデックスデータを作成
vert = Vertex ;
ind = Index ;
AddIndex = 0 ;
for( i = 0 ; i < ONESET_X_NUM; i++ )
{
for( j = 0; j < ONESET_Y_NUM; j++ )
{
for( k = 0; k < ONESET_Z_NUM; k++ )
{
AddPos.x = i * ONE_SPACE - TotalXDistance / 2.0f ;
AddPos.y = j * ONE_SPACE - TotalYDistance / 2.0f ;
AddPos.z = k * ONE_SPACE - TotalZDistance / 2.0f ;
for( l = 0; l < ONE_VERTEXNUM; l++ )
{
*vert = ConeVertex[ l ] ;
vert->pos = VAdd( vert->pos, AddPos ) ;
vert++ ;
}
for( l = 0; l < ONE_INDEXNUM; l++ )
{
*ind = ConeIndex[ l ] + AddIndex ;
ind++ ;
}
AddIndex += ONE_VERTEXNUM ;
}
}
}
// 頂点バッファの作成
VertexBufferHandle = CreateVertexBuffer( ONESET_TOTAL_VERTEXNUM, DX_VERTEX_TYPE_NORMAL_3D ) ;
// 頂点インデックスバッファの作成
IndexBufferHandle = CreateIndexBuffer( ONESET_TOTAL_INDEXNUM, DX_INDEX_TYPE_16BIT ) ;
// 頂点バッファに頂点データを転送
SetVertexBufferData( 0, Vertex, ONESET_TOTAL_VERTEXNUM, VertexBufferHandle ) ;
// 頂点インデックスバッファに頂点インデックスデータを転送
SetIndexBufferData( 0, Index, ONESET_TOTAL_INDEXNUM, IndexBufferHandle ) ;
// 確保していたメモリを解放
free( Vertex ) ;
free( Index ) ;
}
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int i ;
int j ;
int k ;
int FPS ;
int FrameCount ;
LONGLONG BaseTime ;
LONGLONG Time ;
VECTOR CameraPos ;
VECTOR CameraTargetPos ;
MATRIX TranslateMatrix ;
float TotalXDistance ;
float TotalYDistance ;
float TotalZDistance ;
VECTOR TranslateVector ;
int x ;
int xadd ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// VSYNC待ちをしない
SetWaitVSyncFlag( FALSE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 頂点バッファをセットアップ
SetupVertexBuffer() ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// カメラの設定
CameraPos.x = 0.0f ;
CameraPos.y = 0.0f ;
CameraPos.z = -2500.0f ;
SetCameraNearFar( 10.0f, 10000.0f ) ;
CameraTargetPos = VAdd( CameraPos, VGet( 0.0f, 0.0f, 1.0f ) ) ;
SetCameraPositionAndTarget_UpVecY( CameraPos, CameraTargetPos ) ;
// FPSカウントの準備
BaseTime = GetNowHiPerformanceCount() ;
FPS = 0 ;
FrameCount = 0 ;
// 描画範囲を予め計算しておく
TotalXDistance = SET_SPACE * ( SET_X_NUM - 1 ) ;
TotalYDistance = SET_SPACE * ( SET_Y_NUM - 1 ) ;
TotalZDistance = SET_SPACE * ( SET_Z_NUM - 1 ) ;
// 動きの滑らかさを確認するための四角形の位置を移動速度を初期化
x = 0 ;
xadd = 8 ;
// メインループ(何かキーが押されたらループを抜ける)
while( ProcessMessage() == 0 )
{
// 動きの滑らかさを確認するための四角形の位置の移動
x += xadd ;
if( x <= 0 || x >= 640 )
{
xadd = -xadd ;
}
// 画面のクリア
ClearDrawScreen() ;
// Zバッファを使用する設定
SetUseZBufferFlag( TRUE ) ;
SetWriteZBufferFlag( TRUE ) ;
// 円錐を描画
for( i = 0 ; i < SET_X_NUM ; i ++ )
{
for( j = 0 ; j < SET_Y_NUM ; j ++ )
{
for( k = 0 ; k < SET_Z_NUM ; k ++ )
{
// 1セットを描画する位置を設定
TranslateVector.x = i * SET_SPACE - TotalXDistance / 2.0f ;
TranslateVector.y = j * SET_SPACE - TotalYDistance / 2.0f ;
TranslateVector.z = k * SET_SPACE - TotalZDistance / 2.0f ;
TranslateMatrix = MGetTranslate( TranslateVector ) ;
SetTransformToWorld( &TranslateMatrix ) ;
// 1セット描画
DrawPolygonIndexed3D_UseVertexBuffer( VertexBufferHandle, IndexBufferHandle, DX_NONE_GRAPH, FALSE ) ;
}
}
}
// Zバッファを使用する設定を解除
SetWriteZBufferFlag( FALSE ) ;
SetUseZBufferFlag( FALSE ) ;
// 動きの滑らかさを確認するための四角形の描画
DrawBox( x, 448, x + 32, 480, GetColor( 255,255,255 ), TRUE ) ;
// FPSの描画
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "FPS:%d", FPS ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
// フレームカウンタをインクリメント
FrameCount++ ;
// 1秒経過していたら、1秒間の内にカウントしたフレーム数をFPSとしてセットする
Time = GetNowHiPerformanceCount() ;
if( Time - BaseTime > 1000000 )
{
FPS = FrameCount ;
FrameCount = 0 ;
BaseTime = Time ;
}
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
因みにこのプログラムでは見た目が全部同じで全く動かない円錐を描画するということを前提に
高速に描画できるようにしていますので、描画するものの種類が複数あったり
一つ一つが動いたりするなど描画の自由度が増すに従って処理負荷はこのプログラムよりも
2倍、3倍と重くなっていきます
低いスペックとは言えない私が使用しているパソコンでもこのプログラムを実行したところ
FPS が 70 程度でしたので、やはり低いスペックのパソコンで100万個を描画するのは難しいと思います