Added C# project & refactored names

This commit is contained in:
2021-10-05 00:17:24 +13:00
parent 5a78cd9a4b
commit 8ad77f2355
33 changed files with 2839 additions and 0 deletions
@@ -0,0 +1,324 @@
#include "pch.h"
#include "Sample3DSceneRenderer.h"
#include "..\Common\DirectXHelper.h"
using namespace CameraDirect_cpp;
using namespace DirectX;
using namespace Windows::Foundation;
// Loads vertex and pixel shaders from files and instantiates the cube geometry.
Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
m_loadingComplete(false),
m_degreesPerSecond(45),
m_indexCount(0),
m_tracking(false),
m_deviceResources(deviceResources)
{
CreateDeviceDependentResources();
CreateWindowSizeDependentResources();
}
// Initializes view parameters when the window size changes.
void Sample3DSceneRenderer::CreateWindowSizeDependentResources()
{
Size outputSize = m_deviceResources->GetOutputSize();
float aspectRatio = outputSize.Width / outputSize.Height;
float fovAngleY = 70.0f * XM_PI / 180.0f;
// This is a simple example of change that can be made when the app is in
// portrait or snapped view.
if (aspectRatio < 1.0f)
{
fovAngleY *= 2.0f;
}
// Note that the OrientationTransform3D matrix is post-multiplied here
// in order to correctly orient the scene to match the display orientation.
// This post-multiplication step is required for any draw calls that are
// made to the swap chain render target. For draw calls to other targets,
// this transform should not be applied.
// This sample makes use of a right-handed coordinate system using row-major matrices.
XMMATRIX perspectiveMatrix = XMMatrixPerspectiveFovRH(
fovAngleY,
aspectRatio,
0.01f,
100.0f
);
XMFLOAT4X4 orientation = m_deviceResources->GetOrientationTransform3D();
XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);
XMStoreFloat4x4(
&m_constantBufferData.projection,
XMMatrixTranspose(perspectiveMatrix * orientationMatrix)
);
// Eye is at (0,0.7,1.5), looking at point (0,-0.1,0) with the up-vector along the y-axis.
static const XMVECTORF32 eye = { 0.0f, 0.7f, 1.5f, 0.0f };
static const XMVECTORF32 at = { 0.0f, -0.1f, 0.0f, 0.0f };
static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };
XMStoreFloat4x4(&m_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up)));
}
// Called once per frame, rotates the cube and calculates the model and view matrices.
void Sample3DSceneRenderer::Update(DX::StepTimer const& timer)
{
if (!m_tracking)
{
// Convert degrees to radians, then convert seconds to rotation angle
float radiansPerSecond = XMConvertToRadians(m_degreesPerSecond);
double totalRotation = timer.GetTotalSeconds() * radiansPerSecond;
float radians = static_cast<float>(fmod(totalRotation, XM_2PI));
Rotate(radians);
}
}
// Rotate the 3D cube model a set amount of radians.
void Sample3DSceneRenderer::Rotate(float radians)
{
// Prepare to pass the updated model matrix to the shader
XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY(radians)));
}
void Sample3DSceneRenderer::StartTracking()
{
m_tracking = true;
}
// When tracking, the 3D cube can be rotated around its Y axis by tracking pointer position relative to the output screen width.
void Sample3DSceneRenderer::TrackingUpdate(float positionX)
{
if (m_tracking)
{
float radians = XM_2PI * 2.0f * positionX / m_deviceResources->GetOutputSize().Width;
Rotate(radians);
}
}
void Sample3DSceneRenderer::StopTracking()
{
m_tracking = false;
}
// Renders one frame using the vertex and pixel shaders.
void Sample3DSceneRenderer::Render()
{
// Loading is asynchronous. Only draw geometry after it's loaded.
if (!m_loadingComplete)
{
return;
}
auto context = m_deviceResources->GetD3DDeviceContext();
// Prepare the constant buffer to send it to the graphics device.
context->UpdateSubresource1(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0,
0
);
// Each vertex is one instance of the VertexPositionColor struct.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
m_vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->VSSetConstantBuffers1(
0,
1,
m_constantBuffer.GetAddressOf(),
nullptr,
nullptr
);
// Attach our pixel shader.
context->PSSetShader(
m_pixelShader.Get(),
nullptr,
0
);
// Draw the objects.
context->DrawIndexed(
m_indexCount,
0,
0
);
}
void Sample3DSceneRenderer::CreateDeviceDependentResources()
{
// Load shaders asynchronously.
auto loadVSTask = DX::ReadDataAsync(L"SampleVertexShader.cso");
auto loadPSTask = DX::ReadDataAsync(L"SamplePixelShader.cso");
// After the vertex shader file is loaded, create the shader and input layout.
auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateVertexShader(
&fileData[0],
fileData.size(),
nullptr,
&m_vertexShader
)
);
static const D3D11_INPUT_ELEMENT_DESC vertexDesc [] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateInputLayout(
vertexDesc,
ARRAYSIZE(vertexDesc),
&fileData[0],
fileData.size(),
&m_inputLayout
)
);
});
// After the pixel shader file is loaded, create the shader and constant buffer.
auto createPSTask = loadPSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreatePixelShader(
&fileData[0],
fileData.size(),
nullptr,
&m_pixelShader
)
);
CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer) , D3D11_BIND_CONSTANT_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&constantBufferDesc,
nullptr,
&m_constantBuffer
)
);
});
// Once both shaders are loaded, create the mesh.
auto createCubeTask = (createPSTask && createVSTask).then([this] () {
// Load mesh vertices. Each vertex has a position and a color.
static const VertexPositionColor cubeVertices[] =
{
{XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f)},
{XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f)},
{XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f)},
{XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f)},
{XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f)},
{XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f)},
{XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f)},
{XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)},
};
D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
vertexBufferData.pSysMem = cubeVertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(cubeVertices), D3D11_BIND_VERTEX_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&m_vertexBuffer
)
);
// Load mesh indices. Each trio of indices represents
// a triangle to be rendered on the screen.
// For example: 0,2,1 means that the vertices with indexes
// 0, 2 and 1 from the vertex buffer compose the
// first triangle of this mesh.
static const unsigned short cubeIndices [] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
m_indexCount = ARRAYSIZE(cubeIndices);
D3D11_SUBRESOURCE_DATA indexBufferData = {0};
indexBufferData.pSysMem = cubeIndices;
indexBufferData.SysMemPitch = 0;
indexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC indexBufferDesc(sizeof(cubeIndices), D3D11_BIND_INDEX_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&indexBufferDesc,
&indexBufferData,
&m_indexBuffer
)
);
});
// Once the cube is loaded, the object is ready to be rendered.
createCubeTask.then([this] () {
m_loadingComplete = true;
});
}
void Sample3DSceneRenderer::ReleaseDeviceDependentResources()
{
m_loadingComplete = false;
m_vertexShader.Reset();
m_inputLayout.Reset();
m_pixelShader.Reset();
m_constantBuffer.Reset();
m_vertexBuffer.Reset();
m_indexBuffer.Reset();
}
@@ -0,0 +1,50 @@
#pragma once
#include "..\Common\DeviceResources.h"
#include "ShaderStructures.h"
#include "..\Common\StepTimer.h"
namespace CameraDirect_cpp
{
// This sample renderer instantiates a basic rendering pipeline.
class Sample3DSceneRenderer
{
public:
Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources);
void CreateDeviceDependentResources();
void CreateWindowSizeDependentResources();
void ReleaseDeviceDependentResources();
void Update(DX::StepTimer const& timer);
void Render();
void StartTracking();
void TrackingUpdate(float positionX);
void StopTracking();
bool IsTracking() { return m_tracking; }
private:
void Rotate(float radians);
private:
// Cached pointer to device resources.
std::shared_ptr<DX::DeviceResources> m_deviceResources;
// Direct3D resources for cube geometry.
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_inputLayout;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_indexBuffer;
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vertexShader;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pixelShader;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_constantBuffer;
// System resources for cube geometry.
ModelViewProjectionConstantBuffer m_constantBufferData;
uint32 m_indexCount;
// Variables used with the rendering loop.
bool m_loadingComplete;
float m_degreesPerSecond;
bool m_tracking;
};
}
@@ -0,0 +1,122 @@
#include "pch.h"
#include "SampleFpsTextRenderer.h"
#include "Common/DirectXHelper.h"
using namespace CameraDirect_cpp;
using namespace Microsoft::WRL;
// Initializes D2D resources used for text rendering.
SampleFpsTextRenderer::SampleFpsTextRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
m_text(L""),
m_deviceResources(deviceResources)
{
ZeroMemory(&m_textMetrics, sizeof(DWRITE_TEXT_METRICS));
// Create device independent resources
ComPtr<IDWriteTextFormat> textFormat;
DX::ThrowIfFailed(
m_deviceResources->GetDWriteFactory()->CreateTextFormat(
L"Segoe UI",
nullptr,
DWRITE_FONT_WEIGHT_LIGHT,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
32.0f,
L"en-US",
&textFormat
)
);
DX::ThrowIfFailed(
textFormat.As(&m_textFormat)
);
DX::ThrowIfFailed(
m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR)
);
DX::ThrowIfFailed(
m_deviceResources->GetD2DFactory()->CreateDrawingStateBlock(&m_stateBlock)
);
CreateDeviceDependentResources();
}
// Updates the text to be displayed.
void SampleFpsTextRenderer::Update(DX::StepTimer const& timer)
{
// Update display text.
uint32 fps = timer.GetFramesPerSecond();
m_text = (fps > 0) ? std::to_wstring(fps) + L" FPS" : L" - FPS";
ComPtr<IDWriteTextLayout> textLayout;
DX::ThrowIfFailed(
m_deviceResources->GetDWriteFactory()->CreateTextLayout(
m_text.c_str(),
(uint32) m_text.length(),
m_textFormat.Get(),
240.0f, // Max width of the input text.
50.0f, // Max height of the input text.
&textLayout
)
);
DX::ThrowIfFailed(
textLayout.As(&m_textLayout)
);
DX::ThrowIfFailed(
m_textLayout->GetMetrics(&m_textMetrics)
);
}
// Renders a frame to the screen.
void SampleFpsTextRenderer::Render()
{
ID2D1DeviceContext* context = m_deviceResources->GetD2DDeviceContext();
Windows::Foundation::Size logicalSize = m_deviceResources->GetLogicalSize();
context->SaveDrawingState(m_stateBlock.Get());
context->BeginDraw();
// Position on the bottom right corner
D2D1::Matrix3x2F screenTranslation = D2D1::Matrix3x2F::Translation(
logicalSize.Width - m_textMetrics.layoutWidth,
logicalSize.Height - m_textMetrics.height
);
context->SetTransform(screenTranslation * m_deviceResources->GetOrientationTransform2D());
DX::ThrowIfFailed(
m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING)
);
context->DrawTextLayout(
D2D1::Point2F(0.f, 0.f),
m_textLayout.Get(),
m_whiteBrush.Get()
);
// Ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
// is lost. It will be handled during the next call to Present.
HRESULT hr = context->EndDraw();
if (hr != D2DERR_RECREATE_TARGET)
{
DX::ThrowIfFailed(hr);
}
context->RestoreDrawingState(m_stateBlock.Get());
}
void SampleFpsTextRenderer::CreateDeviceDependentResources()
{
DX::ThrowIfFailed(
m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &m_whiteBrush)
);
}
void SampleFpsTextRenderer::ReleaseDeviceDependentResources()
{
m_whiteBrush.Reset();
}
@@ -0,0 +1,31 @@
#pragma once
#include <string>
#include "..\Common\DeviceResources.h"
#include "..\Common\StepTimer.h"
namespace CameraDirect_cpp
{
// Renders the current FPS value in the bottom right corner of the screen using Direct2D and DirectWrite.
class SampleFpsTextRenderer
{
public:
SampleFpsTextRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources);
void CreateDeviceDependentResources();
void ReleaseDeviceDependentResources();
void Update(DX::StepTimer const& timer);
void Render();
private:
// Cached pointer to device resources.
std::shared_ptr<DX::DeviceResources> m_deviceResources;
// Resources related to text rendering.
std::wstring m_text;
DWRITE_TEXT_METRICS m_textMetrics;
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_whiteBrush;
Microsoft::WRL::ComPtr<ID2D1DrawingStateBlock1> m_stateBlock;
Microsoft::WRL::ComPtr<IDWriteTextLayout3> m_textLayout;
Microsoft::WRL::ComPtr<IDWriteTextFormat2> m_textFormat;
};
}
@@ -0,0 +1,10 @@
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 1.0f);
}
@@ -0,0 +1,33 @@
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR0;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f);
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
output.color = input.color;
return output;
}
@@ -0,0 +1,19 @@
#pragma once
namespace CameraDirect_cpp
{
// Constant buffer used to send MVP matrices to the vertex shader.
struct ModelViewProjectionConstantBuffer
{
DirectX::XMFLOAT4X4 model;
DirectX::XMFLOAT4X4 view;
DirectX::XMFLOAT4X4 projection;
};
// Used to send per-vertex data to the vertex shader.
struct VertexPositionColor
{
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
};
}