BaseCrossDx12ドキュメント
【Sample100】Emptyプロジェクト
このサンプルは
Samples/Sample100ディレクトリ内にあります。スタンダードサンプルのEmptyプロジェクトです。VisualStdioで該当ソリューション(VS2022では
BaseCrossDx12VS2022.sln、VS2026では
BaseCrossDx12VS2026.sln)を開いてください。ビルド後実行すると、以下の画面が現れます。
Escキーを押すか
×ボタンで終了します。
Altを押しながら
Enterで、全画面に変更できます。Windowモードに戻すときは、再び
Altを押しながら
Enterを押します。
Emptyプロジェクトのソリューションは以下の通りです。
シーンの役割
スタンダードサンプルも基本的には
シーン(Scene.h/cpp)が中心になります。
以下は
Scene.hです。
//--------------------------------------------------------------------------------------
// シーン
//--------------------------------------------------------------------------------------
class Scene : public BaseScene
{
public:
//--------------------------------------------------------------------------------------
/*!
@brief コンストラクタ、デストラクタ
@param[in] frameCount フレーム数
@param[in] pPrimDevice デバイス
@return なし
*/
//--------------------------------------------------------------------------------------
Scene(UINT frameCount, PrimDevice* pPrimDevice);
virtual ~Scene();
protected:
//--------------------------------------------------------------------------------------
/*!
@brief コンテンツの作成
@param[in] pDevice デバイス
@param[in] pCommandList コマンドリスト
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void CreateAssetResources(ID3D12Device* pDevice, ID3D12GraphicsCommandList* pCommandList)override;
//--------------------------------------------------------------------------------------
/*!
@brief 更新処理
@param[in] elapsedTime 前のターンからの時間
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void Update(double elapsedTime)override;
//--------------------------------------------------------------------------------------
/*!
@brief コンスタントバッファの更新
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void UpdateConstantBuffers()override;
//--------------------------------------------------------------------------------------
/*!
@brief コンスタントバッファのコミット
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void CommitConstantBuffers()override;
//--------------------------------------------------------------------------------------
/*!
@brief UIの更新
@param[in] uiLayer UIレイヤー
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void UpdateUI(std::unique_ptr<UILayer>& uiLayer)override;
//--------------------------------------------------------------------------------------
/*!
@brief シャドウマップの描画
@param[in] コマンドリスト
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void ShadowPass(ID3D12GraphicsCommandList* pCommandList)override;
//--------------------------------------------------------------------------------------
/*!
@brief シーンの描画
@param[in] コマンドリスト
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void ScenePass(ID3D12GraphicsCommandList* pCommandList);
};
このヘッダファイルは
ベーシックサンプルのEmptyプロジェクトとほぼ同じですが
スタンダードサンプルはそれぞれの関数は
何もしないわけではなく実体を持っています。以下がその内容です。
Scene.cppになります。
//--------------------------------------------------------------------------------------
// シーン
//--------------------------------------------------------------------------------------
Scene::Scene(UINT frameCount, PrimDevice* pPrimDevice) :
BaseScene(frameCount, pPrimDevice)
{
}
Scene::~Scene()
{
}
void Scene::CreateAssetResources(ID3D12Device* pDevice, ID3D12GraphicsCommandList* pCommandList)
{
//ステージ作成
ResetActiveStage<GameStage>(pDevice);
}
void Scene::UpdateConstantBuffers() {
if (m_activeStage) {
m_activeStage->OnUpdateConstantBuffers();
}
}
void Scene::CommitConstantBuffers() {
if (m_activeStage) {
m_activeStage->OnCommitConstantBuffers();
}
}
void Scene::UpdateUI(std::unique_ptr<UILayer>& uiLayer) {
auto device = BaseDevice::GetBaseDevice();
//1秒間に1回更新される安定したfpsを得る
auto fps = device->GetStableFps();
//1秒間に1回更新される安定したelapsedTimeを得る
auto elapsedTime = device->GetStableElapsedTime();
std::wstring uiText = L"";
wchar_t buff[512];
swprintf_s(buff, 500, L"FPS: %.1f\n", fps);
uiText = buff;
swprintf_s(buff, 500, L"ElapsedTime: %.6f\n", elapsedTime);
uiText += buff;
uiLayer->UpdateLabels(uiText);
}
void Scene::Update(double elapsedTime) {
s_elapsedTime = elapsedTime;
if (m_activeStage) {
m_activeStage->UpdateStage(elapsedTime);
UpdateConstantBuffers();
CommitConstantBuffers();
}
}
void Scene::ShadowPass(ID3D12GraphicsCommandList* pCommandList) {
if (m_activeStage) {
m_pTgtCommandList = pCommandList;
m_activeStage->OnShadowDraw(pCommandList);
}
}
void Scene::ScenePass(ID3D12GraphicsCommandList* pCommandList)
{
if (m_activeStage) {
m_pTgtCommandList = pCommandList;
m_activeStage->OnSceneDraw(pCommandList);
}
}
ステージの構築
まず、構築時に呼ばれる
Scene::CreateAssetResources()では以下のように
ステージ作成を行います。ここでは
GameStageというクラスのステージを構築します。
void Scene::CreateAssetResources(ID3D12Device* pDevice, ID3D12GraphicsCommandList* pCommandList)
{
//ステージ作成
ResetActiveStage<GameStage>(pDevice);
}
GameStageクラスは、コンテンツ側の
GameStage.h/cppに実装があり、それぞれ以下のような内容です。
以下
GameStage.hです。
//--------------------------------------------------------------------------------------
// ゲームステージ
//--------------------------------------------------------------------------------------
class GameStage : public Stage {
std::shared_ptr<Camera> m_camera;
std::shared_ptr<LightSet> m_lightSet;
public:
GameStage(ID3D12Device* pDevice):
Stage(pDevice)
{}
virtual ~GameStage() {}
virtual void OnCreate()override;
virtual std::shared_ptr<Camera> GetCamera() const override{
return m_camera;
}
virtual std::shared_ptr<LightSet> GetLightSet() const override {
return m_lightSet;
}
virtual void UpdateCameraLight(double elapsedTime) override{
//カメラとライト更新
m_camera->OnUpdate(elapsedTime);
m_lightSet->OnUpdate(elapsedTime);
}
};
Scene::CreateAssetResources()関数で呼んでいる
ResetActiveStage()テンプレート関数では、内部で
GameStage::OnCreate()関数を呼んでいて、その内容は以下になります。
void GameStage::OnCreate() {
//カメラとライトの設定
m_camera = ObjectFactory::Create<PerspecCamera>();
m_camera->SetEye(Vec3(0, 3.43f, -6.37f));
m_camera->SetAt(Vec3(0, 0.125f, 0));
m_lightSet = ObjectFactory::Create<LightSet>();
}
どのみち真っ黒な画面なのでカメラもライトも影響はないのですが、
Emptyプロジェクトは実際にゲームを作成する場合のひな形になりますのでこのような記述になってます。
m_cameraおよび
m_lightSetは、自由度の高い設計になっていて、このサンプルでは
GameStageクラスに実装されてますが、例えば
Playerなどのゲームオブジェクトなどにも設定可能です。つまり、オブジェクトごとに描画するカメラとライトを変えることが可能です。そのあたりのサンプルは後述します。
シーンの更新
シーンの更新は
Scene::Update()関数からステージの更新を行います。
void Scene::Update(double elapsedTime) {
s_elapsedTime = elapsedTime;
if (m_activeStage) {
m_activeStage->UpdateStage(elapsedTime);
UpdateConstantBuffers();
CommitConstantBuffers();
}
}
m_activeStage->UpdateStage()関数は
Stage::UpdateStage()関数を呼び出します。ここでは、ステージに配置されたオブジェクトの更新処理などを行います。仮想関数なのでGameStageなどで多重定義することは可能です。
UpdateConstantBuffers();
CommitConstantBuffers();
は、以下です。
void Scene::UpdateConstantBuffers() {
if (m_activeStage) {
m_activeStage->OnUpdateConstantBuffers();
}
}
void Scene::CommitConstantBuffers() {
if (m_activeStage) {
m_activeStage->OnCommitConstantBuffers();
}
}
それぞれ、ステージのコンスタントバッファの更新とコミットを行います。
シーンの描画
描画処理は
Scene::ShadowPass()関数(シャドウマップ)と
Scene::ScenePass()関数(シーン描画)があります。
それぞれステージの
OnShadowDraw()、OnSceneDraw()関数を呼び出します。これらの関数は、内部で
ゲームオブジェクトの描画関数を呼び出します。それらの記述は、次項以降に説明します。
void Scene::ShadowPass(ID3D12GraphicsCommandList* pCommandList) {
if (m_activeStage) {
m_pTgtCommandList = pCommandList;
m_activeStage->OnShadowDraw(pCommandList);
}
}
void Scene::ScenePass(ID3D12GraphicsCommandList* pCommandList)
{
if (m_activeStage) {
m_pTgtCommandList = pCommandList;
m_activeStage->OnSceneDraw(pCommandList);
}
}
まとめ
この
Emptyプロジェクトは、実際にゲームを作り始めるときの土台となります。
実際のゲームオブジェクトの配置や、描画コンポーネントの指定などは、次項以降に紹介します。