/** * @file * @brief Utility無しのパーティクルサンプル * @date 2009-09-17 Selene ver 1.11にて適当なサンプルソース(Sample.cpp)にコピペ動作確認 */ /*--------------------------------------------------------------------------*/ /* Include */ /*--------------------------------------------------------------------------*/ #include using namespace Selene; static const Uint16 PARTICLE_COUNT = 128; // パーティクル用データ struct S_PARTICLE_DATA { Kernel::Math::VectorS m_vPos; // 位置 Kernel::Math::VectorS m_vVecSpeed;// 速度 ColorF m_Color; // 色 }; // パーティクルデータ作成 static void CreateParticleData( Uint16 uParticleCount, S_PARTICLE_DATA sParticleDataArray[] ); static void GetRandomVector( Kernel::Math::VectorS &vVecOut ); // Seleneコア Engine::ICore* g_pCore = NULL; static const Point2DI SCREEN_SIZE( 512, 512 ); /*--------------------------------------------------------------------------*/ /* WinMain */ /*--------------------------------------------------------------------------*/ int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) { { // ----------------------------------------------------------- // // はじめのお約束作業 // めんどうなのでコメント削除 // // ----------------------------------------------------------- S_PARTICLE_DATA sParticleDataArray[PARTICLE_COUNT]; Engine::Graphics::Resource::Particle::IParticleController *pParticle; Engine::Renderer::Standard::IRenderer* pRenderer = NULL; Engine::Renderer::Standard::SParameter RendererParameter; Kernel::Math::Camera CameraTable[Engine::Renderer::Standard::VIEW_TYPE_MAX]; Engine::Graphics::Resource::ITexture* pTexture = NULL; Engine::File::IFile* pFile = NULL; #if defined(SLN_DEVELOP) if ( !Selene::InitializeEngine( L"Selene.Develop.dll" ) ) #elif defined(SLN_DEBUG) if ( !Selene::InitializeEngine( L"Selene.Debug.dll" ) ) #else // SLN_DEBUG if ( !Selene::InitializeEngine( L"Selene.dll" ) ) #endif { return 1; } g_pCore = Selene::CreateCore(); if ( !g_pCore->Initialize( L"Selene Sample Program", SCREEN_SIZE, true, true ) ) { return 1; } if ( !g_pCore->CreateGraphicsManager() ) { return 1; } if ( !g_pCore->CreateRendererManager() ) { return 1; } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-= // ファイルマネージャーの生成 // ファイル読み込みを行うためのエンジンを初期化 g_pCore->CreateFileManager(); // 暗号解除用プラグイン // ファイルを暗号化してパックしてある場合に // 暗号解除に利用するプラグインと解除用のパスワードを指定 // 暗号化はデータの中身を隠す目的としては有用だが // 当然読み込み速度を犠牲にするので使いどころに注意。 // g_pCore->GetFileManager()->SetCryptPlugin( L"Plugin/File/Crypt.dll", "Sample-Password" ); // ファイル読み込み対象のパスのリスト // 指定ディレクトリ以下を順に検索していく // // Sample/ の Data/test.dat と SampleNew/ の /Data/test.dat があった場合は // 後に指定した方が検索対象として登録される。 // リリース後にパッチ等でデータの差し替え尾を行う場合に // 古い方のデータを変更せずソースの変更もなしで差し替える事が可能 // const wchar_t* pFilePathList[] = { L"../../Media", // 最初に検索するディレクトリ NULL, // NULLで検索終了 }; g_pCore->GetFileManager()->UpdateRootPath( pFilePathList ); pRenderer = g_pCore->GetRendererManager()->CreateStandardRenderer(); RendererParameter.UseProgrammableShader = true; // 利用可能ならシェーダーを使って描画 RendererParameter.Effect.IsFog = false; // フォグの有無 RendererParameter.Effect.IsScattering = false; // スキャッタリングの有無 RendererParameter.Effect.IsDepthOfField = false; // 被写界深度処理の有無 RendererParameter.Effect.IsHighDynamicRange = false; // HDRレンダリングの有無 RendererParameter.Effect.IsSoftParticle = false; // ソフトパーティクルの有無 RendererParameter.Effect.IsMotionBlur = false; // モーションブラーの有無 RendererParameter.Effect.IsAmbientOcclusion = false; // アンビエント隠蔽 RendererParameter.Effect.ShadowType = Engine::Renderer::Standard::SHADOW_MAP_DISABLE; // 影マップの種類 pRenderer->Initialize( RendererParameter ); pRenderer->CreateView( Engine::Renderer::Standard::VIEW_TYPE_01, RectI(0,0,SCREEN_SIZE.x,SCREEN_SIZE.y), true, ColorF(0.0f,0.0f,0.0f,1.0f), true ); pRenderer->SetParameter_MainLight( sVectorS( 0.5f, 2.0f,-2.0f ), // 平行光源の位置 sVectorS( 0.0f, 0.0f, 0.0f ), // 平行光源のターゲット位置 sVectorS( 0.8f, 0.8f, 0.8f ), // 平行光源の色 sVectorS( 0.4f, 0.4f, 0.4f ), // 半球ライトの地面からの照り返し sVectorS( 0.2f, 0.2f, 0.2f ) ); // 半球ライトの空からの色 // ----------------------------------------------------------- // // // ここからが本番 // // // ----------------------------------------------------------- // マップ読み込み // ファイルの読み込みを行う対象のディレクトリへ移動 g_pCore->GetFileManager()->SetCurrentPath( L"Texture" ); // ファイルの読み込みを行う // このメソッドは読み込みが完了するまで関数から戻りません pFile = g_pCore->GetFileManager()->OpenSyncFile( L"particle.bmp" ); if ( pFile != NULL && pFile->IsLoaded() ) { Engine::Graphics::STextureLoadParameter Param; Param.IsCompressFormat = true; // 圧縮テクスチャ Param.IsMipmapEnable = true; // ミップマップあり Param.SizeDivide = 0; // 等倍 Param.ColorKey = ColorF(0.0f,0.0f,0.0f,0.0f); // カラーキーなし // ファイルからテクスチャを生成する pTexture = g_pCore->GetGraphicsManager()->CreateTexture( pFile->GetData(), // データのポインタ pFile->GetSize(), // データのサイズ pFile->GetFileName(), // データの名称(内部で同一名称のファイルを使いまわすようにしています) Param ); SAFE_RELEASE( pFile ); } else SLN_ASSERT( pFile, "ファイル読み込みに失敗しました。" ); // 描画ステート生成 Engine::Graphics::State::IRenderState* pState = g_pCore->GetGraphicsManager()->CreateRenderState(); pState->SetAlphaBlend( Engine::Graphics::State::AB_ADD ); // 加算合成描画 pState->SetCulling( Engine::Graphics::State::CULL_FRONT ); // 前面描画 pState->SetDepthTest( Engine::Graphics::State::DT_ENABLE ); // 深度テストON pState->SetDepthWrite( Engine::Graphics::State::DW_DISABLE ); // 深度書き込みOFF pState->SetPolygonFill( Engine::Graphics::State::PF_SOLID ); // ポリゴン塗りつぶし // パーティクル用マテリアル Engine::Renderer::Standard::Material::IMaterial* pMaterial; pMaterial = g_pCore->GetRendererManager()->CreateStandardRendererMaterial(); pMaterial->SetLightEnable(false); pMaterial->SetDiffuse( sVectorS( 1.0f, 1.0f, 1.0f, 1.0f)); pMaterial->SetTexture(Engine::Renderer::Standard::Material::TEXTURE_STAGE_COLOR, pTexture); // パーティクル用パラメーター Engine::Graphics::Resource::Particle::SParameter Param( pState, pMaterial ); // パーティクルを生成 pParticle = g_pCore->GetGraphicsManager()->CreateParticle( PARTICLE_COUNT, // パーティクル数 Param ); // 不要リソース破棄 SAFE_RELEASE( pMaterial ); SAFE_RELEASE( pState ); SAFE_RELEASE( pTexture ); // ----------------------------------------------------------- // 生成したプリミティブをレンダラーに登録する // これ重要! // ----------------------------------------------------------- pRenderer->AddDrawObject(pParticle, true); // ----------------------------------------------------------- // パーティクルのデータを作成 // ----------------------------------------------------------- CreateParticleData( PARTICLE_COUNT, sParticleDataArray ); //------------------------------------------------------------ // メインループ // Seleneを利用する上でのメインループの書き方です // ICore::DoEvent()でOSのイベント処理を行います。 //------------------------------------------------------------ static float fCameraAngleY = 0.0f; static Uint16 uResetTime = 0; while(g_pCore->DoEvent(60)) { //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // 画面のクリア //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- g_pCore->GetGraphicsManager()->Clear(true, false, ColorF(0.7f,0.7f,0.7f)); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // フレームの開始 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- g_pCore->FrameBegin(); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // カメラの設定 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // パースペクティブ行列 Kernel::Math::Camera *pCamera = &CameraTable[Engine::Renderer::Standard::VIEW_TYPE_01]; pCamera->PerspectiveFovLH( Kernel::Math::DegToPi( 45 ), toF(SCREEN_SIZE.x)/toF(SCREEN_SIZE.y), 0.1f, 2000.0f ); pCamera->LookAt( sVectorS( 0.0f, 10.0f, -45.0f ), // 位置 sVectorS( 0.0f, 0.0f, 0.0f ), // 注視位置 sVectorS( 0.0f, 0.0f, 1.0f ) ); // 上向き角度 // 回転 pCamera->SetWorldMatrix( pCamera->GetViewMatrixInverse() * Kernel::Math::MatX::RotationY( fCameraAngleY ) ); fCameraAngleY += 0.01f; // フラスタム更新 pCamera->UpdateFrustum(); // 一定時間過ぎたら最初から if( uResetTime++ >= 180 ) // 3秒くらい { CreateParticleData( PARTICLE_COUNT, sParticleDataArray ); uResetTime = 0; } // ----------------------------------------------------------- // パーティクル更新 // ----------------------------------------------------------- pParticle->SetSortCamera( *pCamera ); pParticle->Begin( true ); // パーティクル描画プッシュ for( int i = 0; i < PARTICLE_COUNT; i++ ) { S_PARTICLE_DATA *pData = &sParticleDataArray[i]; pData->m_vPos = Kernel::Math::VecS::Add( pData->m_vPos, pData->m_vVecSpeed ); pParticle->DrawRequest( pData->m_vPos, sVector2( 2.0f, 2.0f ), pData->m_Color, RectF( 0.0f, 0.0f, 64.0f, 64.0f ), 1.0f, sVectorS( 0.0f,0.0f,0.0f) ); } pParticle->End(); // ----------------------------------------------------------- // カメラを利用して描画 // pRenderer->AddDrawObjectしたやつを描画するっぽい // ----------------------------------------------------------- pRenderer->SimpleRendering(CameraTable); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // フレームの終了 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- g_pCore->FrameEnd(); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // 画面の更新 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- g_pCore->GetGraphicsManager()->Present(); } //------------------------------------------------------------ // 終了処理 // 終了時には生成したインターフェイスを解放し、 // 最後にICoreを解放してください。 //------------------------------------------------------------ if ( pRenderer != NULL ) { pRenderer->RemoveDrawObject( pParticle ); } SAFE_RELEASE(pRenderer); SAFE_RELEASE(g_pCore); } Selene::FinalizeEngine(); return 0; } //-------------------------------------------------------------------------------- /** * @brief パーティクルデータを作成 * * @param[in] uParticleCount パーティクル数 * @param[in] sParticleDataArray パーティクルデータ配列 **/ //-------------------------------------------------------------------------------- void CreateParticleData( Uint16 uParticleCount, S_PARTICLE_DATA sParticleDataArray[] ) { Kernel::Math::Random Random; Kernel::Timer::SystemTimer CpuTimer; Random.Seed( (Sint32)CpuTimer.Get() ); for( int i = 0; i < uParticleCount; i++ ) { S_PARTICLE_DATA *pData = &sParticleDataArray[i]; pData->m_vPos = Kernel::Math::VecS::Set( 0.0f, 0.0f, 0.0f, 1.0f ); GetRandomVector( pData->m_vVecSpeed ); // 色はランダム pData->m_Color = ColorF( Random.GetFloat(0.0f, 1.0f), Random.GetFloat(0.0f, 1.0f), Random.GetFloat(0.0f, 1.0f), 1.0f); } } //-------------------------------------------------------------------------------- /** * @brief XYZランダムベクトルを取得 * * @param[in/out] vVecOut 格納先 **/ //-------------------------------------------------------------------------------- void GetRandomVector( Kernel::Math::VectorS &vVecOut ) { Kernel::Math::VectorS vVec; Kernel::Math::Random Random; Kernel::Timer::SystemTimer CpuTimer; Random.Seed( (Sint32)CpuTimer.Get() ); // まずはZランダム vVec.z = Random.GetFloat( -1.0f, 1.0f ); // 円の半径取得 float radius = FastSqrt(1 - vVec.z * vVec.z); // 円上のランダム位置 float t = Random.GetFloat( -PI, PI ); // XYのベクトルを算出 vVec.x = Kernel::Math::FastCos(t) * radius; vVec.y = Kernel::Math::FastSin(t) * radius; vVecOut = vVec; }