应用程序名:App1
应用程序源代码:
App1Main.cpp
#include "pch.h"
#include "App1Main.h"
#include "Common\DirectXHelper.h"
using namespace App1;
using namespace Windows::Foundation;
using namespace Windows::System::Threading;
using namespace Concurrency;
// 加载应用程序时加载并初始化应用程序资产。
App1Main::App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
m_deviceResources(deviceResources), m_pointerLocationX(0.0f)
{
// 注册以在设备丢失或重新创建时收到通知
m_deviceResources->RegisterDeviceNotify(this);
// TODO: 将此替换为应用程序内容的初始化。
m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>(new Sample3DSceneRenderer(m_deviceResources));
m_fpsTextRenderer = std::unique_ptr<SampleFpsTextRenderer>(new SampleFpsTextRenderer(m_deviceResources));
// TODO: 如果需要默认的可变时间步长模式之外的其他模式,请更改计时器设置。
// 例如,对于 60 FPS 固定时间步长更新逻辑,请调用:
/*
m_timer.SetFixedTimeStep(true);
m_timer.SetTargetElapsedSeconds(1.0 / 60);
*/
}
App1Main::~App1Main()
{
// 取消注册设备通知
m_deviceResources->RegisterDeviceNotify(nullptr);
}
// 在窗口大小更改(例如,设备方向更改)时更新应用程序状态
void App1Main::CreateWindowSizeDependentResources()
{
// TODO: 将此替换为应用程序内容的与大小相关的初始化。
m_sceneRenderer->CreateWindowSizeDependentResources();
}
void App1Main::StartRenderLoop()
{
// 如果动画呈现循环已在运行,则勿启动其他线程。
if (m_renderLoopWorker != nullptr && m_renderLoopWorker->Status == AsyncStatus::Started)
{
return;
}
// 创建一个将在后台线程上运行的任务。
auto workItemHandler = ref new WorkItemHandler([this](IAsyncAction^ action)
{
// 计算更新的帧并且在每个场消隐期呈现一次。
while (action->Status == AsyncStatus::Started)
{
critical_section::scoped_lock lock(m_criticalSection);
Update();
if (Render())
{
m_deviceResources->Present();
}
}
});
// 在高优先级的专用后台线程上运行任务。
m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
}
void App1Main::StopRenderLoop()
{
m_renderLoopWorker->Cancel();
}
// 每帧更新一次应用程序状态。
void App1Main::Update()
{
ProcessInput();
// 更新场景对象。
m_timer.Tick([&]()
{
// TODO: 将此替换为应用程序内容的更新函数。
m_sceneRenderer->Update(m_timer);
m_fpsTextRenderer->Update(m_timer);
});
}
// 在更新游戏状态之前处理所有用户输入
void App1Main::ProcessInput()
{
// TODO: 按帧输入处理在此处添加。
m_sceneRenderer->TrackingUpdate(m_pointerLocationX);
}
// 根据当前应用程序状态呈现当前帧。
// 如果帧已呈现并且已准备好显示,则返回 true。
bool App1Main::Render()
{
// 在首次更新前,请勿尝试呈现任何内容。
if (m_timer.GetFrameCount() == 0)
{
return false;
}
auto context = m_deviceResources->GetD3DDeviceContext();
// 将视区重置为针对整个屏幕。
auto viewport = m_deviceResources->GetScreenViewport();
context->RSSetViewports(1, &viewport);
// 将呈现目标重置为屏幕。
ID3D11RenderTargetView* const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
// 清除后台缓冲区和深度模具视图。
context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
// 呈现场景对象。
// TODO: 将此替换为应用程序内容的渲染函数。
m_sceneRenderer->Render();
m_fpsTextRenderer->Render();
return true;
}
// 通知呈现器,需要释放设备资源。
void App1Main::OnDeviceLost()
{
m_sceneRenderer->ReleaseDeviceDependentResources();
m_fpsTextRenderer->ReleaseDeviceDependentResources();
}
// 通知呈现器,现在可重新创建设备资源。
void App1Main::OnDeviceRestored()
{
m_sceneRenderer->CreateDeviceDependentResources();
m_fpsTextRenderer->CreateDeviceDependentResources();
CreateWindowSizeDependentResources();
}
DirectXPage.xaml
<Page
x:Class="App1.DirectXPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<SwapChainPanel x:Name="swapChainPanel">
<TextBlock Text="Hello from XAML!"
HorizontalAlignment="Right"
VerticalAlignment="Top"
FontSize="30" />
</SwapChainPanel>
<Page.BottomAppBar>
<AppBar x:Name="bottomAppBar" Padding="10,0,10,0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<AppBarButton AutomationProperties.Name="Sample Button"
AutomationProperties.AutomationId="SampleAppBarButton"
Click="AppBarButton_Click"/>
</StackPanel>
</AppBar>
</Page.BottomAppBar>
</Page>
App1Main.h
#pragma once
#include "Common\StepTimer.h"
#include "Common\DeviceResources.h"
#include "Content\Sample3DSceneRenderer.h"
#include "Content\SampleFpsTextRenderer.h"
// 在屏幕上呈现 Direct2D 和 3D 内容。
namespace App1
{
class App1Main : public DX::IDeviceNotify
{
public:
App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources);
~App1Main();
void CreateWindowSizeDependentResources();
void StartTracking() { m_sceneRenderer->StartTracking(); }
void TrackingUpdate(float positionX) { m_pointerLocationX = positionX; }
void StopTracking() { m_sceneRenderer->StopTracking(); }
bool IsTracking() { return m_sceneRenderer->IsTracking(); }
void StartRenderLoop();
void StopRenderLoop();
Concurrency::critical_section& GetCriticalSection() { return m_criticalSection; }
// IDeviceNotify
virtual void OnDeviceLost();
virtual void OnDeviceRestored();
private:
void ProcessInput();
void Update();
bool Render();
// 缓存的设备资源指针。
std::shared_ptr<DX::DeviceResources> m_deviceResources;
// TODO: 替换为你自己的内容呈现器。
std::unique_ptr<Sample3DSceneRenderer> m_sceneRenderer;
std::unique_ptr<SampleFpsTextRenderer> m_fpsTextRenderer;
Windows::Foundation::IAsyncAction^ m_renderLoopWorker;
Concurrency::critical_section m_criticalSection;
// 渲染循环计时器。
DX::StepTimer m_timer;
//跟踪当前输入指针位置
float m_pointerLocationX;
};
}
应用程序介绍:
这是一个使用DirectX和XAML构建的Windows应用程序。代码使用硬件加速来创建3D图形,可以在屏幕上呈现Direct2D和3D内容。该应用程序初始化时会注册设备,创建并初始化设备资源,以及创建渲染器。渲染器可以呈现3D场景和FPS文本,而计时器可用于计算动画更新帧。应用程序还包括用于处理用户输入,处理设备资源的失去和恢复的方法,以及开始和停止呈现循环的方法。