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プロジェクトは、実際にゲームを作り始めるときの土台となります。
 実際のゲームオブジェクトの配置や、描画コンポーネントの指定などは、次項以降に紹介します。